Portal Delete run (Super Admin), lab codes #3/#4, Z23 pointer #45, T1017 #46, payer note, login security-image wait
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a8af44e673
commit
fafa5285eb
21 files changed
+1509
-63
No files matched your search
@@ -105,6 +105,16 @@ class FakeRepo:
|
||||
self._maybe_fail()
|
||||
return [dict(r) for r in self._rows if claim_no in r["claim_no"]]
|
||||
|
||||
delete_fails = None
|
||||
|
||||
def delete_run(self, run_at):
|
||||
self.calls.append(("delete_run", run_at))
|
||||
if self.delete_fails:
|
||||
raise self.delete_fails
|
||||
kept = [r for r in self._rows if r["run_at"] != run_at]
|
||||
gone, self._rows = len(self._rows) - len(kept), kept
|
||||
return gone
|
||||
|
||||
|
||||
TESTER_PASSWORD = "tester-password-1"
|
||||
|
||||
@@ -581,6 +591,63 @@ def the_error_page_names_what_went_wrong():
|
||||
assert "Smith" not in r.text, "the driver's message is never shown"
|
||||
|
||||
|
||||
# ── Delete a run (Super Admin only, operator 2026-10-28) ─────────────────────
|
||||
|
||||
def _delete_run(client, app, run_at=RUN_PM, token=None):
|
||||
return client.post("/admin/runs/delete", headers=_GOOD_ORIGIN,
|
||||
data={"run_at": run_at.isoformat(),
|
||||
"token": token or app.state.run_token},
|
||||
follow_redirects=False)
|
||||
|
||||
|
||||
@case
|
||||
def a_super_admin_deletes_one_run_and_the_delete_is_recorded():
|
||||
repo = FakeRepo()
|
||||
client, app = signed_in(repo, FakeRunner(), role="Super Admin")
|
||||
page = client.get(f"/day/{DAY.isoformat()}").text
|
||||
assert page.count("Delete run") == 2, "one button per run of the day"
|
||||
r = _delete_run(client, app)
|
||||
assert r.status_code == 303, r.status_code
|
||||
assert r.headers["location"].startswith(f"/day/{DAY.isoformat()}?"), \
|
||||
r.headers["location"]
|
||||
assert [x["run_at"] for x in repo._rows] == [RUN_AM], \
|
||||
"only that run's rows go"
|
||||
shown = client.get(r.headers["location"]).text
|
||||
assert "2 claims deleted" in shown, shown
|
||||
history = client.get("/admin/signins").text
|
||||
assert "run deleted" in history and "10/16/2026 2:15 PM" in history, \
|
||||
history
|
||||
|
||||
|
||||
@case
|
||||
def an_admin_or_viewer_cannot_see_or_use_delete_run():
|
||||
for role in ("Admin", "Viewer"):
|
||||
repo = FakeRepo()
|
||||
client, app = signed_in(repo, FakeRunner(), role=role)
|
||||
assert "Delete run" not in client.get(f"/day/{DAY.isoformat()}").text
|
||||
assert _delete_run(client, app).status_code == 403, role
|
||||
assert len(repo._rows) == 3, (role, "nothing deleted")
|
||||
repo = FakeRepo()
|
||||
client, app = signed_in(repo, FakeRunner(), role="Super Admin")
|
||||
assert _delete_run(client, app, token="wrong").status_code == 403, \
|
||||
"a page on another site cannot send it"
|
||||
assert len(repo._rows) == 3
|
||||
|
||||
|
||||
@case
|
||||
def delete_run_without_the_sql_permission_says_so():
|
||||
class DbError(Exception):
|
||||
pass
|
||||
|
||||
repo = FakeRepo()
|
||||
repo.delete_fails = DbError("42000", "The DELETE permission was denied")
|
||||
client, app = signed_in(repo, FakeRunner(), role="Super Admin")
|
||||
r = _quiet(_delete_run, client, app)
|
||||
assert r.status_code == 503, r.status_code
|
||||
assert "No permission to delete" in r.text, r.text
|
||||
assert "GRANT DELETE" in r.text, r.text
|
||||
|
||||
|
||||
# ── repo SQL ─────────────────────────────────────────────────────────────────
|
||||
|
||||
class FakeCursor:
|
||||
@@ -590,6 +657,7 @@ class FakeCursor:
|
||||
|
||||
def execute(self, sql, params):
|
||||
self.log.append((sql, list(params)))
|
||||
self.rowcount = len(self.rows)
|
||||
return self
|
||||
|
||||
def fetchall(self):
|
||||
@@ -599,10 +667,14 @@ class FakeCursor:
|
||||
class FakeConn:
|
||||
def __init__(self, rows=(), cols=()):
|
||||
self.log, self.rows, self.cols, self.closed = [], list(rows), cols, False
|
||||
self.committed = False
|
||||
|
||||
def cursor(self):
|
||||
return FakeCursor(self.log, self.rows, self.cols)
|
||||
|
||||
def commit(self):
|
||||
self.committed = True
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
@@ -611,6 +683,17 @@ def _repo(conn):
|
||||
return SqlResultsRepo("DSN=x", connect=lambda cs, timeout: conn)
|
||||
|
||||
|
||||
@case
|
||||
def repo_deletes_exactly_one_run_and_commits():
|
||||
conn = FakeConn(rows=[None] * 20) # the driver's rowcount: 20
|
||||
assert _repo(conn).delete_run(RUN_PM) == 20
|
||||
(sql, params), = conn.log
|
||||
assert re.fullmatch(r"DELETE FROM dbo\.CV_ChargeSummary WHERE run_at = \?",
|
||||
sql), sql
|
||||
assert params == [RUN_PM], params
|
||||
assert conn.committed and conn.closed
|
||||
|
||||
|
||||
@case
|
||||
def repo_turns_a_text_run_at_or_day_into_a_datetime_or_date():
|
||||
"""The legacy {SQL Server} driver returns DATETIME2 / DATE as text."""
|
||||
|
||||
Reference in new issue
Block a user