From 48abe0bca13607329db0766a0b545b473508afe2 Mon Sep 17 00:00:00 2001 From: elof-dev Date: Thu, 23 Oct 2025 09:24:42 +0700 Subject: [PATCH] Fix/invalid bookings (empty, zero, non-numeric or negative values) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Updated purchasePlaces() to handle invalid inputs: • Added a check for empty input • Added a try/except block to catch non-numeric values • Added a condition to reject zero or negative values - Created test_invalid_number_of_places_booking.py: • Test 1: valid booking (success) • Test 2: zero places (error) • Test 3: negative places (error) • Test 4: empty input (error) • Test 5: non-numeric input (error) --- server.py | 20 ++++- .../test_invalid_number_of_places_booking.py | 90 +++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_invalid_number_of_places_booking.py diff --git a/server.py b/server.py index e53d984e2..adb583048 100644 --- a/server.py +++ b/server.py @@ -59,9 +59,27 @@ def purchasePlaces(): MAX_BOOKING = 12 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']) + + places = request.form.get('places') + if not places: + flash("Please enter a number of places.") + return render_template('welcome.html', club=club, competitions=competitions) + + # même si on a vérifié dans le formulaire sur le HTML avec un input de type "number", + # on doit quand même gérer le cas où un utilisateur malveillant envoie une valeur non numérique + # en modifiant via les outils de développement du navigateur. + try: + placesRequired = int(places) + except ValueError: + flash("Invalid number of places.") + return render_template('welcome.html', club=club, competitions=competitions) + club_points = int(club['points']) + if placesRequired <= 0: + flash("Invalid number of places.") + return render_template('welcome.html', club=club, competitions=competitions) + if placesRequired > club_points: flash("Cannot book more places than club points.") return render_template('welcome.html', club=club, competitions=competitions) diff --git a/tests/unit/test_invalid_number_of_places_booking.py b/tests/unit/test_invalid_number_of_places_booking.py new file mode 100644 index 000000000..f817113ff --- /dev/null +++ b/tests/unit/test_invalid_number_of_places_booking.py @@ -0,0 +1,90 @@ +import server + +""" +Unit test file to verify that the booking system correctly handles invalid number of places inputs + +Test 1: booking with valid number of places -> success, points and places updated +Test 2 :booking with 0 places -> error message, number of places and points unchanged +Test 3: booking with negative places -> error message, number of places and points unchanged +Test 4: booking without providing number of places -> error message, number of places and points unchanged +Test 5: booking with non-numeric input -> error message, number of places and points unchanged +""" + +def test_booking_valid_number_of_places(client): + server.clubs = [{"name": "Club A", "points": "10"}] + server.competitions = [{"name": "Comp 1", "numberOfPlaces": "20"}] + + response = client.post('/purchasePlaces', data={ + 'competition': 'Comp 1', + 'club': 'Club A', + 'places': '3' + }) + + assert response.status_code == 200 + assert b"Great - booking complete!" in response.data + assert int(server.clubs[0]['points']) == 7 + assert int(server.competitions[0]['numberOfPlaces']) == 17 + + +def test_booking_zero_places(client): + server.clubs = [{"name": "Club A", "points": "10"}] + server.competitions = [{"name": "Comp 1", "numberOfPlaces": "20"}] + + response = client.post('/purchasePlaces', data={ + 'competition': 'Comp 1', + 'club': 'Club A', + 'places': '0' + }) + + assert response.status_code == 200 + assert b"Invalid number of places." in response.data + assert int(server.competitions[0]['numberOfPlaces']) == 20 + assert int(server.clubs[0]['points']) == 10 + + +def test_booking_negative_places(client): + server.clubs = [{"name": "Club A", "points": "10"}] + server.competitions = [{"name": "Comp 1", "numberOfPlaces": "20"}] + + response = client.post('/purchasePlaces', data={ + 'competition': 'Comp 1', + 'club': 'Club A', + 'places': '-5' + }) + + assert response.status_code == 200 + assert b"Invalid number of places." in response.data + assert int(server.competitions[0]['numberOfPlaces']) == 20 + assert int(server.clubs[0]['points']) == 10 + + +def test_booking_without_places_value(client): + server.clubs = [{"name": "Club A", "points": "10"}] + server.competitions = [{"name": "Comp 1", "numberOfPlaces": "20"}] + + response = client.post('/purchasePlaces', data={ + 'competition': 'Comp 1', + 'club': 'Club A', + 'places': '' + }) + + assert response.status_code == 200 + assert b"Please enter a number of places." in response.data + assert int(server.competitions[0]['numberOfPlaces']) == 20 + assert int(server.clubs[0]['points']) == 10 + + +def test_booking_with_non_numeric_input(client): + server.clubs = [{"name": "Club A", "points": "10"}] + server.competitions = [{"name": "Comp 1", "numberOfPlaces": "20"}] + + response = client.post('/purchasePlaces', data={ + 'competition': 'Comp 1', + 'club': 'Club A', + 'places': 'abc' + }) + + assert response.status_code == 200 + assert b"Invalid number of places." in response.data + assert int(server.competitions[0]['numberOfPlaces']) == 20 + assert int(server.clubs[0]['points']) == 10