from pathlib import Path
 
 import click
-from flask import g, current_app
+from flask import abort, g, current_app
 
 from . import datadir
 
     if db is not None:
         db.close()
 
-def query(query, args=(), one=False):
+def query(query, args=(), one=False, expect_one=False):
     cur = get().execute(query, args)
     rv = cur.fetchall()
     cur.close()
-    return (rv[0] if rv else None) if one else rv
+    if expect_one and not rv:
+        abort(404)  # Not found
+
+    return (rv[0] if rv else None) if (one or expect_one) else rv
 
 def commit():
     get().commit()
 
 from dataclasses import dataclass
 from datetime import datetime, timezone
 
-from flask import Blueprint, g, redirect, render_template, request, url_for
+from flask import abort, Blueprint, g, redirect, render_template, request, url_for
 
 from . import auth, db
 from .sanitize import sanitize_user_text
             """, [g.userid, timestamp, f"New Jam"], one=True)
     db.commit()
     jamid = row["jamid"]
-    return redirect(url_for('jams.jam', jamid=jamid))
+    return redirect(url_for("jams.jam", jamid=jamid))
 
 @bp.get("/<int:jamid>")
 def jam(jamid):
             SELECT * FROM jams
             INNER JOIN users ON jams.ownerid = users.userid
             WHERE jamid = ?
-            """, [jamid], one=True)
-    print(type(jamid), row)
+            """, [jamid], expect_one=True)
+
     jam = Jam.from_row(row)
     # Show the main jam page
     return render_template("jam.html", jam=jam)
     # Update a jam with the new form data, redirect to view page
     title = request.form["title"]
     description = request.form["description"]
-    db.query(
+    row = db.query(
             """
             UPDATE jams
             SET title = ?, description = ?
             WHERE jamid = ?
-            """, [title, description, jamid])
+            RETURNING *
+            """, [title, description, jamid], expect_one=True)
+
     db.commit()
-    return redirect(url_for('jams.jam', jamid=jamid))
+    return redirect(url_for("jams.jam", jamid=jamid))
 
 @bp.get("/<int:jamid>/delete")
 @auth.requires_login
 def delete(jamid):
     # Delete a jam, redirect to the jams list
-    ...
+    row = db.query(
+            "DELETE FROM jams WHERE jamid = ? RETURNING *",
+            [jamid], expect_one=True)
+
+    db.commit()
+    return redirect(url_for("jams.jams"))
 
 @bp.get("/<int:jamid>/events")
 def events(jamid):
 
     client.get("/jams/create")
     return 1
 
+def test_view_invalid_jam(client):
+    response = client.get("/jams/1")
+    assert response.status_code == 404
+
 def test_create_jam(client, user):
     response = client.get("/jams/create", follow_redirects=True)
     assert response.status_code == 200
     assert b"Coolest Jam" in response.data
     assert b"pb and jam" in response.data
 
+def test_update_invalid_jam(client, user):
+    response = client.post(
+            "/jams/1/update",
+            data={"title": "Coolest Jam", "description": "pb and jam"})
+    assert response.status_code == 404
+
+def test_delete_jam(client, user, jam):
+    response = client.get(f"/jams/{jam}/delete", follow_redirects=True)
+    assert response.request.path == "/jams/"
+    assert b"New Jam" not in response.data
+
+    response = client.get(f"/jams/{jam}")
+    assert response.status_code == 404
+
+def test_delete_invalid_jam(client, user):
+    response = client.get("/jams/1/delete")
+    assert response.status_code == 404