Skip to content

Commit 247bb57

Browse files
committed
(fix) Handle redeeming more points than available
1 parent 9304c72 commit 247bb57

File tree

8 files changed

+370
-42
lines changed

8 files changed

+370
-42
lines changed

.coverage

0 Bytes
Binary file not shown.

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ MarkupSafe==1.1.1
66
Werkzeug==1.0.1
77
pytest
88
black
9-
flake8
9+
flake8

server.py

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,66 @@ def book(competition, club):
6262
)
6363

6464

65+
def get_competition_from_name(name):
66+
try:
67+
competition = [
68+
competition for competition in
69+
competitions if competition["name"] == name
70+
][0]
71+
return competition
72+
except IndexError:
73+
return None
74+
75+
76+
def get_club_from_name(name):
77+
try:
78+
club = [
79+
club for club in clubs if club["name"] == name
80+
][0]
81+
return club
82+
except IndexError:
83+
return None
84+
85+
86+
def check_places(places, club):
87+
if not places or int(places) < 1:
88+
return "Places required must be a positive integer"
89+
if int(places) > int(club["points"]):
90+
return "Places required exceed club's total points"
91+
92+
93+
def take_places(places, club, competition):
94+
try:
95+
competition["numberOfPlaces"] = \
96+
int(competition["numberOfPlaces"]) - places
97+
club["points"] = int(club["points"]) - places
98+
return True
99+
except Exception:
100+
return False
101+
102+
65103
@app.route("/purchasePlaces", methods=["POST"])
66104
def purchasePlaces():
67-
competition = [
68-
c for c in competitions if c["name"] == request.form["competition"]
69-
][0]
70-
club = [c for c in clubs if c["name"] == request.form["club"]][0]
105+
competition = get_competition_from_name(request.form["competition"])
106+
club = get_club_from_name(request.form["club"])
107+
108+
error_message = check_places(request.form["places"], club)
109+
if error_message:
110+
flash(error_message)
111+
return redirect(
112+
url_for("book", competition=competition["name"], club=club["name"])
113+
)
71114
placesRequired = int(request.form["places"])
72-
competition["numberOfPlaces"] = (
73-
int(competition["numberOfPlaces"]) - placesRequired
74-
)
75-
flash("Great-booking complete!")
76-
return render_template("welcome.html", club=club, competitions=competitions)
77115

78-
79-
# TODO: Add route for points display
116+
if take_places(placesRequired, club, competition):
117+
flash("Great-booking complete!")
118+
return render_template("welcome.html", club=club,
119+
competitions=competitions)
120+
else:
121+
flash("Something went wrong-please try again")
122+
return redirect(
123+
url_for("book", competition=competition["name"], club=club["name"])
124+
)
80125

81126

82127
@app.route("/logout")

templates/booking.html

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!DOCTYPE html>
12
<html lang="en">
23
<head>
34
<meta charset="UTF-8">
@@ -6,11 +7,20 @@
67
</head>
78
<body>
89
<h2>{{competition['name']}}</h2>
10+
{% with messages = get_flashed_messages()%}
11+
{% if messages %}
12+
<ul>
13+
{% for message in messages %}
14+
<li>{{message}}</li>
15+
{% endfor %}
16+
</ul>
17+
{% endif%}
18+
{% endwith %}
919
Places available: {{competition['numberOfPlaces']}}
1020
<form action="/purchasePlaces" method="post">
1121
<input type="hidden" name="club" value="{{club['name']}}">
1222
<input type="hidden" name="competition" value="{{competition['name']}}">
13-
<label for="places">How many places?</label><input type="number" name="places" id=""/>
23+
<label for="places">How many places?</label><input type="number" name="places" id="places"/>
1424
<button type="submit">Book</button>
1525
</form>
1626
</body>

tests/integration_tests/conftest.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@
33
from unittest.mock import mock_open, patch
44

55
# Mock data for clubs.json and competitions.json
6-
mock_clubs_json = json.dumps(
7-
{
8-
"clubs": [
9-
{"name": "Club 1", "email": "club1@example.com"},
10-
{"name": "Club 2", "email": "club2@example.com"},
11-
]
12-
}
13-
)
14-
15-
mock_competitions_json = json.dumps(
16-
{
17-
"competitions": [
18-
{"name": "Competition 1", "numberOfPlaces": "25"},
19-
{"name": "Competition 2", "numberOfPlaces": "15"},
20-
]
21-
}
22-
)
6+
mock_clubs_json = json.dumps({
7+
"clubs": [
8+
{"name": "Club 1", "email": "club1@example.com", "points": "10"},
9+
{"name": "Club 2", "email": "club2@example.com", "points": "15"}
10+
]
11+
})
12+
13+
mock_competitions_json = json.dumps({
14+
"competitions": [
15+
{"name": "Competition 1", "date": "2023-03-27 10:00:00",
16+
"numberOfPlaces": "25"},
17+
{"name": "Competition 2", "date": "2023-10-22 13:30:00",
18+
"numberOfPlaces": "15"}
19+
]
20+
})
2321

2422

2523
def mocked_open(file, *args, **kwargs):
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
3+
def test_purchase_places_valid(client):
4+
"""
5+
Test purchasing places with valid club points and valid competition.
6+
"""
7+
response = client.post("/purchasePlaces", data={
8+
"competition": "Competition 1",
9+
"club": "Club 1",
10+
"places": "5"
11+
})
12+
13+
assert response.status_code == 200
14+
assert b"Great-booking complete!" in response.data
15+
16+
17+
def test_purchase_places_insufficient_points(client):
18+
"""
19+
Test purchasing more places than the club's available points.
20+
"""
21+
response = client.post("/purchasePlaces", data={
22+
"competition": "Competition 1",
23+
"club": "Club 1",
24+
"places": "20" # Club 1 has only 10 points
25+
})
26+
27+
assert response.status_code == 302 # Redirect expected
28+
response = client.get(response.headers["Location"]) # Follow the redirect
29+
assert b"Places required exceed club&#39;s total points" in response.data
30+
31+
32+
def test_purchase_places_zero_places(client):
33+
"""
34+
Test purchasing zero places, which is an invalid input.
35+
"""
36+
response = client.post("/purchasePlaces", data={
37+
"competition": "Competition 1",
38+
"club": "Club 1",
39+
"places": "0"
40+
})
41+
42+
assert response.status_code == 302 # Redirect expected
43+
response = client.get(response.headers["Location"]) # Follow the redirect
44+
assert b"Places required must be a positive integer" in response.data

0 commit comments

Comments
 (0)