diff --git a/app/main/routes.py b/app/main/routes.py index 7f29e0d..911e7c3 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -1,5 +1,4 @@ -import json -from typing import Optional, Tuple, Union +from typing import Tuple, Union from flask import Response, flash, make_response, redirect, render_template, request from flask_wtf.csrf import CSRFError # type: ignore @@ -25,39 +24,37 @@ def accessibility() -> str: def cookies() -> Union[str, Response]: """Handle GET and POST requests for managing cookie preferences.""" form: CookiesForm = CookiesForm() - # Initialize cookie policy. Defaults to rejecting all cookies. - cookies_policy: dict[str, str] = {"functional": "no", "analytics": "no"} + # Initialize cookie settings. Defaults to rejecting all cookies. + functional: str = "no" + analytics: str = "no" if form.validate_on_submit(): - # Update cookie policy based on form submission. - cookies_policy["functional"] = form.functional.data - cookies_policy["analytics"] = form.analytics.data + # Update cookie settings based on form submission + functional = form.functional.data + analytics = form.analytics.data # Create flash message confirmation before rendering template flash("You've set your cookie preferences.", "success") - # Create the response so we can set the cookie before returning + # Create the response so we can set cookies before returning response: Response = make_response(render_template("cookies.html", form=form)) - # Set the cookies_policy cookie in the response - response.set_cookie( - "cookies_policy", - json.dumps(cookies_policy), - max_age=31557600, # One year - secure=True, - samesite="Lax", - ) + + # Set individual cookies in the response + cookie_params = { + "max_age": 31557600, + "secure": True, + "samesite": "Lax", + } # One year + response.set_cookie("functional", functional, **cookie_params) + response.set_cookie("analytics", analytics, **cookie_params) + return response elif request.method == "GET": - # Retrieve existing cookie policy if present. - cookies_string: Optional[str] = request.cookies.get("cookies_policy") - if cookies_string: - try: - # Set cookie consent radios to current consent - cookies_policy = json.loads(cookies_string) - form.functional.data = cookies_policy["functional"] - form.analytics.data = cookies_policy["analytics"] - except json.JSONDecodeError: - # If conset not previously set, use default "no" policy - form.functional.data = cookies_policy["functional"] - form.analytics.data = cookies_policy["analytics"] + # Retrieve existing cookie settings if present + functional = request.cookies.get("functional", "no") + analytics = request.cookies.get("analytics", "no") + + # Pre-populate form with existing settings + form.functional.data = functional + form.analytics.data = analytics return render_template("cookies.html", form=form) diff --git a/tests/test_main_routes.py b/tests/test_main_routes.py new file mode 100644 index 0000000..62e478c --- /dev/null +++ b/tests/test_main_routes.py @@ -0,0 +1,92 @@ +import pytest +from flask import Flask +from flask.testing import FlaskClient + +from app import create_app +from config import TestConfig + + +@pytest.fixture +def app() -> FlaskClient: + """ + Create and configure a new app instance for each test. + + Returns: + Flask: The Flask application instance. + """ + app: Flask = create_app(TestConfig) + app.config["WTF_CSRF_ENABLED"] = False # Disable CSRF for testing + with app.test_client() as client: + yield client + + +def test_index(app: FlaskClient) -> None: + """ + Test the index route. + + Args: + client (FlaskClient): The test client for the Flask application. + """ + response = app.get("/") + assert response.status_code == 200 + assert b"" in response.data + + +def test_accessibility(app: FlaskClient) -> None: + """ + Test the accessibility route. + + Args: + client (FlaskClient): The test client for the Flask application. + """ + response = app.get("/accessibility") + assert response.status_code == 200 + assert b"<title>" in response.data + + +def test_privacy(app: FlaskClient) -> None: + """ + Test the privacy route. + + Args: + client (FlaskClient): The test client for the Flask application. + """ + response = app.get("/privacy") + assert response.status_code == 200 + assert b"<title>" in response.data + + +def test_cookies_get(app: FlaskClient) -> None: + """Test the cookies route with a GET request.""" + response = app.get("/cookies") + assert response.status_code == 200 + + # Check default cookie values + assert response.request.cookies.get("functional", "no") == "no" + assert response.request.cookies.get("analytics", "no") == "no" + + +def test_cookies_post(app: FlaskClient) -> None: + """Test the cookies route with a POST request.""" + data = {"functional": "yes", "analytics": "yes"} + + response = app.post("/cookies", data=data, follow_redirects=True) + assert response.status_code == 200 + + # Verify flash message + assert b"You've set your cookie preferences." in response.data + + # Check individual cookies were set + cookies = response.headers.getlist("Set-Cookie") + functional_cookie = [c for c in cookies if c.startswith("functional=")][0] + analytics_cookie = [c for c in cookies if c.startswith("analytics=")][0] + + # Verify cookie values + assert "functional=yes" in functional_cookie + assert "analytics=yes" in analytics_cookie + + # Verify cookie attributes + for cookie in [functional_cookie, analytics_cookie]: + assert "Max-Age=31557600" in cookie + assert "Secure" in cookie + assert "SameSite=Lax" in cookie