Skip to content

Feature/implement display points #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def show_summary():
if request.method == "POST":
email = request.form.get("email")
if not email:
flash("Email is required.")
flash("Empty field.")
return redirect(url_for("index"))

# Find the club by email from the form data
Expand All @@ -91,14 +91,12 @@ def show_summary():
# Handle GET request
email = session.get("email")
if not email:
flash("Session expired. Please log in again.")
return redirect(url_for("index"))
raise Unauthorized("You must be connected.")

# Find the club by email from the session data
club = next((club for club in clubs if club["email"] == email), None)
if not club:
flash("Email does not exist.")
return redirect(url_for("index"))
raise Unauthorized("You must have an account.")

# Update the booking status for each competition
now = datetime.now()
Expand All @@ -122,10 +120,16 @@ def book(competition, club):
otherwise the welcome page with an error message.
:rtype: werkzeug.wrappers.Response
"""

if not session.get("email"):
raise Unauthorized("You must be connected.")

found_club = [c for c in clubs if c["name"] == club][0]
found_competition = [c for c in competitions if c["name"] == competition][0]
if found_club and found_competition:

if found_club and found_competition and found_competition["canBeBooked"] is True:
return render_template("booking.html", club=found_club, competition=found_competition)

flash("Something went wrong - please try again.")
return redirect(url_for("show_summary"))

Expand Down Expand Up @@ -180,7 +184,20 @@ def purchase_places():
@app.route("/logout")
def logout():
"""Log out and redirect to the index page."""
session.pop("email", None)
return redirect(url_for("index"))


# TODO: Add route for points display
@app.route("/clubs", methods=["GET"])
def display_club_points():
"""
Render the club points table page if the user is authenticated.

:raises Unauthorized: If the user is not logged in.
:return: The rendered template for the clubs page.
:rtype: flask.Response
"""
if not session.get("email"):
raise Unauthorized("You must be connected.")

return render_template("clubs.html", clubs=clubs)
81 changes: 81 additions & 0 deletions templates/clubs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Club Points | GUDLFT Clubs</title>
<style>
#clubTable {
border-collapse: collapse;
width: 80%;
max-width: 800px;
margin: 20px auto;
}

#clubTable th,
#clubTable td {
border: 1px solid black;
padding: 8px;
text-align: left;
}

#clubTable th {
background-color: #f2f2f2;
}

.header {
display: flex;
justify-content: space-between;
align-items: center;
width: 80%;
max-width: 800px;
margin: 0 auto;
}

.back-button {
background: #f2f2f2;
border: 1px solid #ddd;
padding: 5px 10px;
text-decoration: none;
color: black;
font-weight: bold;
}

.back-button:hover {
color: blue;
}

h2 {
margin: 0;
text-align: center;
flex-grow: 1;
}
</style>
</head>

<body>
<div class="header">
<a class="back-button" href="{{ url_for('show_summary') }}">>> Retour</a>
<h2>Club Points</h2>
</div>

<table id="clubTable">
<thead>
<tr>
<th>Club Name</th>
<th>Points</th>
</tr>
</thead>
<tbody>
{% for c in clubs %}
<tr>
<td>{{ c.name }}</td>
<td>{{ c.points }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>

</html>
1 change: 1 addition & 0 deletions templates/welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

<body>
<h2>Welcome, {{ club['email'] }}</h2><a href="{{ url_for('logout') }}">Logout</a>
<a class="clubs-button" href="{{url_for('display_club_points')}}">>> Show Club Points</a>

{% with messages = get_flashed_messages(with_categories=True) %}
<p>Points available: {{ club['points'] }}</p>
Expand Down
61 changes: 56 additions & 5 deletions tests/integration_tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def test_login_no_email(client):
response = client.post("/show_summary", data={}, follow_redirects=True)
response_text = response.data.decode("utf-8")
assert response.status_code == 200
assert "Email is required" in response_text
assert "Empty field" in response_text


def test_get_welcome_page_with_email_in_session(client, mocker):
Expand Down Expand Up @@ -142,8 +142,7 @@ def test_get_welcome_page_without_email_in_session(client):
:return: None
"""
response = client.get("/show_summary")
assert response.status_code == 302
assert response.headers["Location"] == "/"
assert response.status_code == 401


def test_get_welcome_page_with_invalid_email_in_session(client):
Expand All @@ -161,8 +160,7 @@ def test_get_welcome_page_with_invalid_email_in_session(client):
sess["email"] = "invalid@example.com"

response = client.get("/show_summary")
assert response.status_code == 302
assert response.headers["Location"] == "/"
assert response.status_code == 401


def test_purchase_success(client, mocker):
Expand Down Expand Up @@ -423,3 +421,56 @@ def test_initialize_club_bookings_count_if_not_present(client, mocker):
client.post("/purchase_places", data={"competition": competitions[0]["name"], "club": clubs[0]["name"], "places": 1}, follow_redirects=True)

assert competitions[0]["clubBookings"]["Club1"] == 1


def test_display_club_points_authenticated(client, mocker):
"""
Test that the clubs page is rendered correctly when the user is authenticated.

This test mocks the club data and simulates a logged-in user session.
It then sends a GET request to the `/clubs` route and checks:

- The HTTP response status code is 200 (OK).
- The names of the clubs are present in the rendered HTML.

:param client: The Flask test client used to simulate requests.
:type client: flask.testing.FlaskClient
:param mocker: The pytest mock object used for patching functions and variables.
:type mocker: pytest_mock.MockerFixture
"""
# Mock club data
clubs = [
{"name": "Club1", "points": 20},
{"name": "Club2", "points": 30},
]
mocker.patch("server.clubs", clubs)

# Simulate a session with a logged-in user
with client.session_transaction() as session:
session["email"] = "club1@test.com"

response = client.get("/clubs")

assert response.status_code == 200
assert b"Club1" in response.data
assert b"Club2" in response.data


def test_display_club_points_unauthenticated(client):
"""
Test that an unauthenticated user is redirected to the index page.

This test sends a GET request to the `/clubs` route without a logged-in user session.
It checks:

- The HTTP response status code is 200 after the redirect.
- A flash message is displayed informing the user they must be logged in.
- The redirect leads to the index page.

:param client: The Flask test client used to simulate requests.
:type client: flask.testing.FlaskClient
"""

response = client.get("/clubs", follow_redirects=True)

assert response.status_code == 401