@bp.get("/<int:jamid>")
def jam(jamid):
- jam = get_jam_by_id(jamid)
+ jam = _get_jam_by_id(jamid)
# Show the main jam page
return render_template("jam.html", jam=jam)
@bp.get("/<int:jamid>/events/<int:eventid>")
def events_view(jamid, eventid):
# Show the event page
- jam = get_jam_by_id(jamid)
+ jam = _get_jam_by_id(jamid)
try:
event = next(e for e in jam.events if e.eventid == eventid)
except StopIteration:
@jam_owner_only
def events_update(jamid, eventid):
# Update an event with the new form data
- ...
+ title = request.form["title"]
+ description = request.form["description"]
+ startdate = request.form["startdate"]
+ enddate = request.form["enddate"]
+ _validate_timestamp(startdate)
+ _validate_timestamp(enddate)
+ db.query(
+ """
+ UPDATE jam_events
+ SET title = ?, description = ?, startdate = ?, enddate = ?
+ WHERE eventid = ? AND jamid = ?
+ RETURNING *
+ """,
+ [title, description, startdate, enddate, eventid, jamid],
+ expect_one=True)
+ db.commit()
+ return redirect(url_for("jams.events_view", jamid=jamid, eventid=eventid))
@bp.get("/<int:jamid>/events/<int:eventid>/delete")
@jam_owner_only
def events_delete(jamid, eventid):
# Delete an event, redirect to list of all events
- ...
+ db.query(
+ """
+ DELETE FROM jam_events
+ WHERE eventid = ? AND jamid = ?
+ RETURNING *
+ """, [eventid, jamid], expect_one=True)
+ return redirect(url_for("jams.jam", jamid=jamid))
+
-def get_jam_by_id(jamid):
+def _get_jam_by_id(jamid):
row = db.query(
"""
SELECT * FROM jams
""", [jamid], expect_one=True)
return Jam.from_row(row)
+
+def _validate_timestamp(timestamp):
+ try:
+ datetime.fromisoformat(timestamp)
+ except ValueError:
+ abort(400)
+
@dataclass
class Jam:
jamid: int
threadid=row["threadid"],
created=datetime.fromisoformat(row["created"]),
title=row["title"],
- startdate=datetime.fromisoformat(row["startdate"]) if "startdate" in row else None,
- enddate=datetime.fromisoformat(row["enddate"]) if "enddate" in row else None,
+ startdate=datetime.fromisoformat(row["startdate"]) if row["startdate"] else None,
+ enddate=datetime.fromisoformat(row["enddate"]) if row["enddate"] else None,
description=sanitize_user_text(row["description"] or ""),
jam_title=row["jam_title"],
jam_ownername=row["jam_ownername"],
+from datetime import datetime, timezone
+
import pytest
from .utils import create_user
yield "user"
@pytest.fixture
-def jam(client):
+def jam(client, user):
client.get("/jams/create")
return 1
+@pytest.fixture
+def event(client, jam):
+ client.get(f"/jams/{jam}/events/create")
+ return 1
+
# Jams #########################################################################
def test_view_invalid_jam(client):
response = client.get(f"/jams/{jam}/events/create", follow_redirects=True)
assert response.status_code == 403
-# Update event
-# Update event invalid event
-# Update event not logged in
-# Update event other users jam
+def _to_utc(timestamp):
+ return (datetime
+ .fromisoformat(timestamp)
+ .astimezone(timezone.utc)
+ .isoformat())
+
+def _get_event_data(**kwargs):
+ event_data = {
+ "title": "Event Title",
+ "description": "description of the event",
+ "startdate": _to_utc("2040-01-01T00:00:00"),
+ "enddate": _to_utc("2040-01-02T00:00:00"),
+ }
+ for k, v in kwargs.items():
+ event_data[k] = v
+ return event_data
+
+def test_update_event(client, user, jam, event):
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(), follow_redirects=True)
+ assert response.request.path == f"/jams/{jam}/events/{event}"
+ assert b"Event Title" in response.data
+ assert b"description of the event" in response.data
+ assert b"2040-01-01" in response.data
+ assert b"2040-01-02" in response.data
+
+def test_update_event_invalid_eventid(client, user, jam):
+ response = client.post(f"/jams/{jam}/events/1/update", data=_get_event_data())
+ assert response.status_code == 404
+
+def test_update_event_invalid_jamid(client, user, event):
+ response = client.post(f"/jams/2/events/{event}/update", data=_get_event_data())
+ assert response.status_code == 404
+
+def test_update_event_not_logged_in(client, user, jam, event):
+ response = client.get("/logout")
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(),
+ follow_redirects=True)
+ assert response.request.path == "/login"
+
+def test_update_event_other_users_jam(client, user, jam, event):
+ create_user(client, "otheruser", login=True)
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(),
+ follow_redirects=True)
+ assert response.status_code == 403
+
+def test_update_event_invalid_startdate(client, user, jam, event):
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(startdate="notadate"),
+ follow_redirects=True)
+ assert response.status_code == 400
+
+def test_update_event_invalid_enddate(client, user, jam, event):
+ response = client.post(
+ f"/jams/{jam}/events/{event}/update",
+ data=_get_event_data(enddate="notadate"),
+ follow_redirects=True)
+ assert response.status_code == 400
+
+def test_delete_event(client, user, jam, event):
+ response = client.get(f"/jams/{jam}/events/{event}/delete", follow_redirects=True)
+ assert response.request.path == f"/jams/{jam}"
+ assert b"Event Title" not in response.data
-# Delete event
-# Delete event not logged in
-# Delete event invalid event
-# Delete event other users jam
+def test_delete_event_not_logged_in(client, user, jam, event):
+ client.get("/logout")
+ response = client.get(f"/jams/{jam}/events/{event}/delete", follow_redirects=True)
+ assert response.request.path == "/login"
+
+def test_delete_event_invalid_jamid(client, user, jam, event):
+ response = client.get(f"/jams/2/events/{event}/delete", follow_redirects=True)
+ assert response.status_code == 404
+
+def test_delete_event_invalid_eventid(client, user, jam, event):
+ response = client.get(f"/jams/{jam}/events/2/delete", follow_redirects=True)
+ assert response.status_code == 404
+
+def test_delete_event_other_users_jam(client, user, jam, event):
+ create_user(client, "otheruser", login=True)
+ response = client.get(f"/jams/{jam}/events/{event}/delete", follow_redirects=True)
+ assert response.status_code == 403