From 7a3ba11c0558d2b738aaf0df1752c221faa99803 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 31 Jan 2025 17:23:37 +0100 Subject: [PATCH 01/13] first commit add test folder --- .gitignore | 1 - server.py | 21 ++++++++++++------- tests/__init__.py | 0 tests/conftest.py | 27 ++++++++++++++++++++++++ tests/test_purchase_place.py | 40 ++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/test_purchase_place.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/server.py b/server.py index 4084baeac..d5114dd2e 100644 --- a/server.py +++ b/server.py @@ -1,35 +1,39 @@ import json from flask import Flask,render_template,request,redirect,flash,url_for - +#load the clubs and competitions from the json files def loadClubs(): with open('clubs.json') as c: listOfClubs = json.load(c)['clubs'] return listOfClubs - +#load the clubs and competitions from the json files def loadCompetitions(): with open('competitions.json') as comps: listOfCompetitions = json.load(comps)['competitions'] return listOfCompetitions -app = Flask(__name__) -app.secret_key = 'something_special' +app = Flask(__name__) #create the Flask app +app.secret_key = 'something_special' #used to add a session flash +#load the clubs and competitions competitions = loadCompetitions() clubs = loadClubs() @app.route('/') def index(): + # user can connect from a form (by email) return render_template('index.html') +#display welcome page after connextion @app.route('/showSummary',methods=['POST']) def showSummary(): + #look for the club in the list of clubs club = [club for club in clubs if club['email'] == request.form['email']][0] return render_template('welcome.html',club=club,competitions=competitions) - +#display the booking page @app.route('/book//') def book(competition,club): foundClub = [c for c in clubs if c['name'] == club][0] @@ -40,11 +44,14 @@ def book(competition,club): flash("Something went wrong-please try again") return render_template('welcome.html', club=club, competitions=competitions) - +#purchase places @app.route('/purchasePlaces',methods=['POST']) def purchasePlaces(): + #look for the competition and the club in the list of clubs and competitions competition = [c for c in competitions if c['name'] == request.form['competition']][0] + #look for the club in the list of clubs club = [c for c in clubs if c['name'] == request.form['club']][0] + #check if there are enough places placesRequired = int(request.form['places']) competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired flash('Great-booking complete!') @@ -56,4 +63,4 @@ def purchasePlaces(): @app.route('/logout') def logout(): - return redirect(url_for('index')) \ No newline at end of file + return redirect(url_for('index')) 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..1e5a747d1 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,27 @@ +import pytest +from server import app + +@pytest.fixture(scope="module") +def client(): + """Fixture pour créer un client de test Flask""" + app.config["TESTING"] = True + app.config["SECRET_KEY"] = "test_secret" + with app.test_client() as client: + yield client + + +@pytest.fixture(scope="function") +def setup_data(monkeypatch): + mock_competitions = [ + {"name": "Competition 1", "numberOfPlaces": "20"}, + {"name": "Competition 2", "numberOfPlaces": "5"} + ] + mock_clubs = [ + {"name": "Club A", "email": "clubA@example.com", "points": "10"}, + {"name": "Club B", "email": "clubB@example.com", "points": "3"} + ] + + monkeypatch.setattr("server.competitions", mock_competitions) + monkeypatch.setattr("server.clubs", mock_clubs) + + return mock_competitions, mock_clubs diff --git a/tests/test_purchase_place.py b/tests/test_purchase_place.py new file mode 100644 index 000000000..90896eac6 --- /dev/null +++ b/tests/test_purchase_place.py @@ -0,0 +1,40 @@ +import pytest + +def test_purchase_places_success(client, setup_data): + #TEST can purchase places + competitions, _ = setup_data + response = client.post('/purchasePlaces', data={ + 'competition': 'Competition 1', + 'club': 'Club A', + 'places': '5' + }) + + assert response.status_code == 200 + assert b"Great-booking complete!" in response.data + assert int(competitions[0]['numberOfPlaces']) == 15 + +def test_purchase_places_not_enough_places(client, setup_data): + #TEST cant buy if not enough places + competitions, _ = setup_data + response = client.post('/purchasePlaces', data={ + 'competition': 'Competition 2', + 'club': 'Club A', + 'places': '10' + }) + + assert response.status_code == 200 + assert b"Not enough places available." in response.data + assert int(competitions[1]['numberOfPlaces']) == 5 + +def test_purchase_places_more_than_12(client, setup_data): + #TEST cant buy more than 12 places + competitions, _ = setup_data + response = client.post('/purchasePlaces', data={ + 'competition': 'Competition 1', + 'club': 'Club A', + 'places': '13' + }) + + assert response.status_code == 200 + assert b"You cannot book more than 12 places per competition." in response.data + assert int(competitions[0]['numberOfPlaces']) == 20 From d49cfcdde06c2a428aa331d1414b9fb63e9d65e4 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Thu, 6 Feb 2025 15:34:18 +0100 Subject: [PATCH 02/13] fix: redirect index when wrong credentials --- server.py | 11 +++++++---- templates/index.html | 11 ++++++++++- tests/test_purchase_place.py | 4 ++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/server.py b/server.py index d5114dd2e..c54c04727 100644 --- a/server.py +++ b/server.py @@ -27,11 +27,14 @@ def index(): return render_template('index.html') #display welcome page after connextion -@app.route('/showSummary',methods=['POST']) -def showSummary(): +@app.route('/show_summary',methods=['POST']) +def show_summary(): #look for the club in the list of clubs - club = [club for club in clubs if club['email'] == request.form['email']][0] - return render_template('welcome.html',club=club,competitions=competitions) + for club in clubs: + if club['email'] == request.form['email']: + return render_template('welcome.html',club=club,competitions=competitions) + flash("Wrong credentials, please retry", "error") + return redirect(url_for('index')) #display the booking page @app.route('/book//') diff --git a/templates/index.html b/templates/index.html index 926526b7d..28e4da4b2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,10 +7,19 @@

Welcome to the GUDLFT Registration Portal!

Please enter your secretary email to continue: -
+
+{% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} +
    + {% for category, message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} +{% endwith %} \ No newline at end of file diff --git a/tests/test_purchase_place.py b/tests/test_purchase_place.py index 90896eac6..9b64db5b3 100644 --- a/tests/test_purchase_place.py +++ b/tests/test_purchase_place.py @@ -22,7 +22,7 @@ def test_purchase_places_not_enough_places(client, setup_data): 'places': '10' }) - assert response.status_code == 200 + assert response.status_code == 400 assert b"Not enough places available." in response.data assert int(competitions[1]['numberOfPlaces']) == 5 @@ -35,6 +35,6 @@ def test_purchase_places_more_than_12(client, setup_data): 'places': '13' }) - assert response.status_code == 200 + assert response.status_code == 400 assert b"You cannot book more than 12 places per competition." in response.data assert int(competitions[0]['numberOfPlaces']) == 20 From 7b2b22d15d2899123e094a1a3757db9461d2775e Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Thu, 6 Feb 2025 17:15:00 +0100 Subject: [PATCH 03/13] feat: test login --- pytest.ini | 3 +++ tests/test_show_summary.py | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 pytest.ini create mode 100644 tests/test_show_summary.py diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..c24fe5bb9 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +filterwarnings = + ignore::DeprecationWarning diff --git a/tests/test_show_summary.py b/tests/test_show_summary.py new file mode 100644 index 000000000..a82510519 --- /dev/null +++ b/tests/test_show_summary.py @@ -0,0 +1,16 @@ +import pytest + +def test_welcome_page_when_loading_accepted(client, setup_data): + """TEST: The welcome page should load when credentials are correct""" + response = client.post('/show_summary', data={'email': 'clubA@example.com'}) + + assert response.status_code == 200 + assert b"Welcome" in response.data + assert b"Competition 1" in response.data + +def test_error_when_wrong_credentials(client, setup_data): + """TEST: Wrong credentials should redirect to index with an error message""" + response = client.post('/show_summary', data={'email': 'fake@example.com'}, follow_redirects=True) + + assert response.status_code == 200 + assert b"Wrong credentials, please retry" in response.data From eb11a0908e6ef0f5901ac3ddf1b4a2fec8068150 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 7 Feb 2025 13:52:32 +0100 Subject: [PATCH 04/13] fix: purchaseplace and can get show_summary --- server.py | 65 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/server.py b/server.py index c54c04727..53f980d2c 100644 --- a/server.py +++ b/server.py @@ -27,37 +27,56 @@ def index(): return render_template('index.html') #display welcome page after connextion -@app.route('/show_summary',methods=['POST']) +@app.route('/show_summary',methods=['POST','GET']) def show_summary(): - #look for the club in the list of clubs - for club in clubs: - if club['email'] == request.form['email']: - return render_template('welcome.html',club=club,competitions=competitions) + email = request.form.get("email") if request.method == "POST" else request.args.get("email") + club = next((club for club in clubs if club['email'] == email), None) + + if club: + return render_template('welcome.html', club=club, competitions=competitions) + flash("Wrong credentials, please retry", "error") return redirect(url_for('index')) #display the booking page -@app.route('/book//') -def book(competition,club): - foundClub = [c for c in clubs if c['name'] == club][0] - foundCompetition = [c for c in competitions if c['name'] == competition][0] - if foundClub and foundCompetition: - return render_template('booking.html',club=foundClub,competition=foundCompetition) - else: - flash("Something went wrong-please try again") - return render_template('welcome.html', club=club, competitions=competitions) +@app.route('/book//', methods=['GET', 'POST']) +def book(competition, club): + found_club = next((c for c in clubs if c['name'] == club), None) + found_competition = next((c for c in competitions if c['name'] == competition), None) + + if not found_club or not found_competition: + flash("Something went wrong - Please try again", "error") + return redirect(url_for('index')) + + return render_template("booking.html", club=found_club, competition=found_competition) + #purchase places -@app.route('/purchasePlaces',methods=['POST']) +@app.route('/purchasePlaces', methods=['POST']) def purchasePlaces(): - #look for the competition and the club in the list of clubs and competitions - competition = [c for c in competitions if c['name'] == request.form['competition']][0] - #look for the club in the list of clubs - club = [c for c in clubs if c['name'] == request.form['club']][0] - #check if there are enough places - placesRequired = int(request.form['places']) - competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired - flash('Great-booking complete!') + competition = next((c for c in competitions if c['name'] == request.form['competition']), None) + club = next((c for c in clubs if c['name'] == request.form['club']), None) + + if not competition or not club: + flash("Something went wrong - Please try again", "error") + return redirect(url_for('index')) + + user_places_required = int(request.form['places']) + + if user_places_required <= 0: + flash("You must book at least one place.", "error") + elif user_places_required > int(competition['numberOfPlaces']): + flash("Not enough places available.", "error") + elif user_places_required > int(club["points"]): + flash("Not enough points available.", "error") + elif user_places_required > 12: + flash("You cannot book more than 12 places per competition.", "error") + else: + competition['numberOfPlaces'] = int(competition['numberOfPlaces']) - user_places_required + club['points'] = int(club['points']) - user_places_required + flash(f"Great! Booking complete for {user_places_required} places!", "success") + return redirect(url_for('show_summary', email=club['email'])) + return render_template('welcome.html', club=club, competitions=competitions) From 20a4ccabaf470e61ebb14352159e9852ad82741f Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 7 Feb 2025 13:52:55 +0100 Subject: [PATCH 05/13] fix: can display flashes --- templates/booking.html | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/templates/booking.html b/templates/booking.html index 06ae1156c..bc14f59bc 100644 --- a/templates/booking.html +++ b/templates/booking.html @@ -7,11 +7,21 @@

{{competition['name']}}

Places available: {{competition['numberOfPlaces']}} -
+ - + +
+{% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} +
    + {% for category, message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} +{% endwith %} \ No newline at end of file From 79a4550532cbc6f9c1668664afb6ea9302e4e231 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 7 Feb 2025 14:06:11 +0100 Subject: [PATCH 06/13] feat: test purchase places --- server.py | 4 ++++ tests/test_purchase_place.py | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 53f980d2c..ad5d1f10c 100644 --- a/server.py +++ b/server.py @@ -65,12 +65,16 @@ def purchasePlaces(): if user_places_required <= 0: flash("You must book at least one place.", "error") + return render_template('welcome.html', club=club, competitions=competitions), 400 elif user_places_required > int(competition['numberOfPlaces']): flash("Not enough places available.", "error") + return render_template('welcome.html', club=club, competitions=competitions), 400 elif user_places_required > int(club["points"]): flash("Not enough points available.", "error") + return render_template('welcome.html', club=club, competitions=competitions), 400 elif user_places_required > 12: flash("You cannot book more than 12 places per competition.", "error") + return render_template('welcome.html', club=club, competitions=competitions), 400 else: competition['numberOfPlaces'] = int(competition['numberOfPlaces']) - user_places_required club['points'] = int(club['points']) - user_places_required diff --git a/tests/test_purchase_place.py b/tests/test_purchase_place.py index 9b64db5b3..ffa9751b7 100644 --- a/tests/test_purchase_place.py +++ b/tests/test_purchase_place.py @@ -9,8 +9,8 @@ def test_purchase_places_success(client, setup_data): 'places': '5' }) - assert response.status_code == 200 - assert b"Great-booking complete!" in response.data + print(f"toto {response.data}") + assert response.status_code == 302 assert int(competitions[0]['numberOfPlaces']) == 15 def test_purchase_places_not_enough_places(client, setup_data): @@ -36,5 +36,16 @@ def test_purchase_places_more_than_12(client, setup_data): }) assert response.status_code == 400 - assert b"You cannot book more than 12 places per competition." in response.data assert int(competitions[0]['numberOfPlaces']) == 20 + +def test_purchase_places_not_enough_points(client, setup_data): + # TEST cant buy if not enough points + _, clubs = setup_data + response = client.post('/purchasePlaces', data={ + 'competition': 'Competition 1', + 'club': 'Club B', + 'places': '5' + }) + + assert response.status_code == 400 + assert int(clubs[1]['points']) == 3 From e4e52b5e85a99f412e8c9e21dfc5b99a1b966ded Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Wed, 12 Feb 2025 23:34:32 +0100 Subject: [PATCH 07/13] fix: test_purchase_place --- tests/test_purchase_place.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_purchase_place.py b/tests/test_purchase_place.py index ffa9751b7..1497feb54 100644 --- a/tests/test_purchase_place.py +++ b/tests/test_purchase_place.py @@ -9,7 +9,6 @@ def test_purchase_places_success(client, setup_data): 'places': '5' }) - print(f"toto {response.data}") assert response.status_code == 302 assert int(competitions[0]['numberOfPlaces']) == 15 @@ -31,12 +30,14 @@ def test_purchase_places_more_than_12(client, setup_data): competitions, _ = setup_data response = client.post('/purchasePlaces', data={ 'competition': 'Competition 1', - 'club': 'Club A', - 'places': '13' + 'club': 'Club C', + 'places': '15' }) assert response.status_code == 400 assert int(competitions[0]['numberOfPlaces']) == 20 + assert b"You cannot book more than 12 places per competition." in response.data + def test_purchase_places_not_enough_points(client, setup_data): # TEST cant buy if not enough points @@ -46,6 +47,7 @@ def test_purchase_places_not_enough_points(client, setup_data): 'club': 'Club B', 'places': '5' }) - + assert response.status_code == 400 assert int(clubs[1]['points']) == 3 + assert b"Not enough points available." in response.data From ad276ad10be2de605af05217a0d0f94a331c16c2 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Thu, 13 Feb 2025 00:05:26 +0100 Subject: [PATCH 08/13] feat: display point club --- server.py | 12 ++++--- templates/display_points_club.html | 54 ++++++++++++++++++++++++++++++ templates/welcome.html | 1 + tests/conftest.py | 5 +-- 4 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 templates/display_points_club.html diff --git a/server.py b/server.py index ad5d1f10c..e9405c4e2 100644 --- a/server.py +++ b/server.py @@ -31,12 +31,12 @@ def index(): def show_summary(): email = request.form.get("email") if request.method == "POST" else request.args.get("email") club = next((club for club in clubs if club['email'] == email), None) - + if club: return render_template('welcome.html', club=club, competitions=competitions) flash("Wrong credentials, please retry", "error") - return redirect(url_for('index')) + return redirect(url_for('index')), 400 #display the booking page @app.route('/book//', methods=['GET', 'POST']) @@ -83,9 +83,13 @@ def purchasePlaces(): return render_template('welcome.html', club=club, competitions=competitions) +@app.route('/display_points_club', methods=['POST','GET']) +def display_points_club(): + """Affiche les points des clubs et garde le contexte du club connecté""" + email = request.form.get("email") if request.method == "POST" else request.args.get("email") + club = next((club for club in clubs if club['email'] == email), None) -# TODO: Add route for points display - + return render_template('display_points_club.html', clubs=clubs, club=club) @app.route('/logout') def logout(): diff --git a/templates/display_points_club.html b/templates/display_points_club.html new file mode 100644 index 000000000..d7a21f7ea --- /dev/null +++ b/templates/display_points_club.html @@ -0,0 +1,54 @@ + + + + + Table | Club Points Overview | GUDLFT + + + +

Club Points Table

+ + + + + + {% for club in clubs %} + + + + + {% endfor %} +
Club NameTotal Points Available
{{ club['name'] }}{{ club['points'] }}
+
+

Return to home page

+ + diff --git a/templates/welcome.html b/templates/welcome.html index ff6b261a2..e8b447046 100644 --- a/templates/welcome.html +++ b/templates/welcome.html @@ -31,6 +31,7 @@

Competitions:

{% endfor %} {%endwith%} +

View Club Points

\ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 1e5a747d1..866db0439 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,11 +14,12 @@ def client(): def setup_data(monkeypatch): mock_competitions = [ {"name": "Competition 1", "numberOfPlaces": "20"}, - {"name": "Competition 2", "numberOfPlaces": "5"} + {"name": "Competition 2", "numberOfPlaces": "5"}, ] mock_clubs = [ {"name": "Club A", "email": "clubA@example.com", "points": "10"}, - {"name": "Club B", "email": "clubB@example.com", "points": "3"} + {"name": "Club B", "email": "clubB@example.com", "points": "3"}, + {"name": "Club C", "email": "clubC@example.com", "points": "15"}, ] monkeypatch.setattr("server.competitions", mock_competitions) From ebdaa8517fe9738a17da24d5f2ff346db96325b1 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 14 Feb 2025 13:28:44 +0100 Subject: [PATCH 09/13] fix: manage showsummary error if no email --- server.py | 7 ++++++- tests/test_show_summary.py | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/server.py b/server.py index e9405c4e2..71fc64003 100644 --- a/server.py +++ b/server.py @@ -30,13 +30,18 @@ def index(): @app.route('/show_summary',methods=['POST','GET']) def show_summary(): email = request.form.get("email") if request.method == "POST" else request.args.get("email") + + if not email: + flash("Email is required. Please login.", "error") + return redirect(url_for('index')) + club = next((club for club in clubs if club['email'] == email), None) if club: return render_template('welcome.html', club=club, competitions=competitions) flash("Wrong credentials, please retry", "error") - return redirect(url_for('index')), 400 + return redirect(url_for('index')) #display the booking page @app.route('/book//', methods=['GET', 'POST']) diff --git a/tests/test_show_summary.py b/tests/test_show_summary.py index a82510519..252cab153 100644 --- a/tests/test_show_summary.py +++ b/tests/test_show_summary.py @@ -14,3 +14,10 @@ def test_error_when_wrong_credentials(client, setup_data): assert response.status_code == 200 assert b"Wrong credentials, please retry" in response.data + +def test_error_when_no_email(client, setup_data): + """TEST: No email inputed should redirect to index with an error message""" + response = client.post('/show_summary', data={'email': ''}, follow_redirects=True) + + assert response.status_code == 200 + assert b"Email is required. Please login." in response.data From 1f5bbecf89d186e8ec4b3511b038a6fe060ea305 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 14 Feb 2025 13:29:07 +0100 Subject: [PATCH 10/13] fix: renaming --- tests/test_purchase_place.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_purchase_place.py b/tests/test_purchase_place.py index 1497feb54..92f111d42 100644 --- a/tests/test_purchase_place.py +++ b/tests/test_purchase_place.py @@ -12,7 +12,7 @@ def test_purchase_places_success(client, setup_data): assert response.status_code == 302 assert int(competitions[0]['numberOfPlaces']) == 15 -def test_purchase_places_not_enough_places(client, setup_data): +def test_cant_purchase_places_not_enough_places(client, setup_data): #TEST cant buy if not enough places competitions, _ = setup_data response = client.post('/purchasePlaces', data={ @@ -25,7 +25,7 @@ def test_purchase_places_not_enough_places(client, setup_data): assert b"Not enough places available." in response.data assert int(competitions[1]['numberOfPlaces']) == 5 -def test_purchase_places_more_than_12(client, setup_data): +def test_cant_purchase_places_more_than_12(client, setup_data): #TEST cant buy more than 12 places competitions, _ = setup_data response = client.post('/purchasePlaces', data={ @@ -39,7 +39,7 @@ def test_purchase_places_more_than_12(client, setup_data): assert b"You cannot book more than 12 places per competition." in response.data -def test_purchase_places_not_enough_points(client, setup_data): +def test_cant_purchase_places_not_enough_points(client, setup_data): # TEST cant buy if not enough points _, clubs = setup_data response = client.post('/purchasePlaces', data={ From 88a50816a64209b8ced38d92f871b54d2506f581 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 14 Feb 2025 13:29:26 +0100 Subject: [PATCH 11/13] feat: test booking page --- tests/test_booking_page.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/test_booking_page.py diff --git a/tests/test_booking_page.py b/tests/test_booking_page.py new file mode 100644 index 000000000..d785dcfcf --- /dev/null +++ b/tests/test_booking_page.py @@ -0,0 +1,8 @@ +import pytest + +def test_booking_page_when_club_not_found(client, setup_data): + """TEST: The booking page should load when credentials are correct""" + response = client.get('/book/Competition 5/Club D', follow_redirects=True) + + assert response.status_code == 200 + assert b"Something went wrong - Please try again" in response.data From 79c72de9d1c5335c2472ec48c9bc53b57c1f8946 Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 14 Feb 2025 14:06:45 +0100 Subject: [PATCH 12/13] feat: readme --- .gitignore | 3 ++- README.md | 79 +++++++++++++++++++++++++++++------------------------- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 950060a15..fe057cdd4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ include lib .Python .envrc -__pycache__ \ No newline at end of file +__pycache__ +.vscode \ No newline at end of file diff --git a/README.md b/README.md index 61307d2cd..8f7daa265 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,56 @@ -# gudlift-registration +# GÜDLFT : Projet d'école [OpenClassrooms](https://openclassrooms.com/fr) - Améliorez une application Web Python par des tests et du débogage -1. Why +GUDLFT est une application web conçue pour les organisateurs de compétitions locales et régionales. L'application permet aux secrétaires de clubs de réserver des places pour des compétitions en utilisant les points accumulés, tout en garantissant une participation équitable entre tous les clubs. - This is a proof of concept (POC) project to show a light-weight version of our competition booking platform. The aim is the keep things as light as possible, and use feedback from the users to iterate. +## Installation et exécution -2. Getting Started +### Prérequis - This project uses the following technologies: +- Python 3.9 ou version supérieur +- pip (gestionnaire de paquets Python) - * Python v3.x+ +### Étapes d'installation - * [Flask](https://flask.palletsprojects.com/en/1.1.x/) +1. **Cloner le dépôt** : + ```bash + git clone https://github.com/Jbguerin13/Python_Testing.git + cd gudlft/PYTHON_TESTING + ``` - Whereas Django does a lot of things for us out of the box, Flask allows us to add only what we need. - +2. **Créer un environnement virtuel** : + Sous Windows : + ```bash + python -m venv env + env\Scripts\activate + ``` + Sous macOS/Linux : + ```bash + python3 -m venv env + source env/bin/activate + ``` - * [Virtual environment](https://virtualenv.pypa.io/en/stable/installation.html) +3. **Installer les dépendances** : + ```bash + pip install -r requirements.txt + ``` - This ensures you'll be able to install the correct packages without interfering with Python on your machine. +4. **Lancer le serveur** : + ```bash + export FLASK_APP=server.py + flask run + ``` - Before you begin, please ensure you have this installed globally. +5. **📌 Fonctionnalités** : + - **Authentification des utilisateurs** : Connexion par e-mail pour les secrétaires de clubs. + - **Système de réservation** : Utilisation des points des clubs pour réserver des places aux compétitions. + - **Gestion des points** : Affichage du solde des points et mise à jour après réservation. + - **Limites de réservation** : Un club ne peut pas réserver plus de 12 places par compétition. + - **Tableau des points** : Affichage public des points de tous les clubs pour assurer la transparence. -3. Installation - - - After cloning, change into the directory and type virtualenv .. This will then set up a a virtual python environment within that directory. - - - Next, type source bin/activate. You should see that your command prompt has changed to the name of the folder. This means that you can install packages in here without affecting affecting files outside. To deactivate, type deactivate - - - Rather than hunting around for the packages you need, you can install in one step. Type pip install -r requirements.txt. This will install all the packages listed in the respective file. If you install a package, make sure others know by updating the requirements.txt file. An easy way to do this is pip freeze > requirements.txt - - - Flask requires that you set an environmental variable to the python file. However you do that, you'll want to set the file to be server.py. Check [here](https://flask.palletsprojects.com/en/1.1.x/quickstart/#a-minimal-application) for more details - - - You should now be ready to test the application. In the directory, type either flask run or python -m flask run. The app should respond with an address you should be able to go to using your browser. - -4. Current Setup - - The app is powered by [JSON files](https://www.tutorialspoint.com/json/json_quick_guide.htm). This is to get around having a DB until we actually need one. The main ones are: - - * competitions.json - list of competitions - * clubs.json - list of clubs with relevant information. You can look here to see what email addresses the app will accept for login. - -5. Testing - - You are free to use whatever testing framework you like-the main thing is that you can show what tests you are using. - - We also like to show how well we're testing, so there's a module called - [coverage](https://coverage.readthedocs.io/en/coverage-5.1/) you should add to your project. +6. **Lancement des tests** : + ```bash + make test + ``` From 4d01ecb90bbeee4a8e00c368f21ee9e7a08df3aa Mon Sep 17 00:00:00 2001 From: "jean-baptiste.guerin" Date: Fri, 14 Feb 2025 14:06:58 +0100 Subject: [PATCH 13/13] feat: Makefile --- Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..b3955fbd0 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +PYTHON := python +PYTEST := pytest + +TEST_FILES := \ + tests/test_purchase_place.py \ + tests/test_booking_page.py \ + tests/test_show_summary.py + +# Commande pour exécuter tous les tests +test: + $(PYTEST) $(TEST_FILES) + +help: + @echo " test Exécute les tests Pytest" + @echo " help Affiche cette aide" + +.PHONY: test install run clean help