remove dead my-sea invite accept/decline endpoints — acceptance is now implicit on bud-page sea-btn visit (accept-on-GET)
The @mailman Post's OK/BYE block + _invite_actions.html were dropped by the
bud-landing-page sprint; with accept-on-GET on my_sea_visit shipped in f5ee83b
the explicit endpoints have no trigger left. Removes:
- my_sea_invite_accept / my_sea_invite_decline views + the _sea_invite_for_request
/ _redirect_to_invite_log helpers they alone used (gameboard/views.py)
- the my-sea/invite/accept + my-sea/invite/decline URL routes (gameboard/urls.py)
- _invite_actions.html partial (already un-included from post.html)
- MySeaInviteAcceptDeclineTest (gameboard ITs); MySeaInvitePostRenderTest now
asserts the form actions are gone by literal path/class instead of reverse()
There is no decline surface now — an un-clicked invite simply lapses after 24h.
post.html comment trimmed to match. 515 gameboard+billboard ITs/UTs green.
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,12 @@
|
||||
"""ITs for the my-sea invite endpoints + post.html OK/BYE render — Phase A
|
||||
(A5/A6) of [[my-sea-invite-voice-blueprint]].
|
||||
"""ITs for the my-sea invite send endpoint + the @mailman Post render.
|
||||
|
||||
Covers the real `my_sea_invite` (replaces the "coming soon" stub), the
|
||||
`my_sea_invite_accept` / `my_sea_invite_decline` transitions + auth gating,
|
||||
and the interactive OK/BYE / status-badge render in the invitee's
|
||||
"Acceptances & rejections" Post.
|
||||
Covers the real `my_sea_invite` (replaces the "coming soon" stub) and the
|
||||
prose-only render of the invitee's "Acceptances & rejections" Post. The
|
||||
explicit accept/decline endpoints were removed 2026-05-29 — acceptance is now
|
||||
implicit on the bud-page sea-btn visit (see test_sea_visit.py's accept-on-GET
|
||||
coverage); an un-clicked invite simply lapses after 24h.
|
||||
"""
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
@@ -80,63 +78,6 @@ class MySeaInviteViewTest(TestCase):
|
||||
self.assertIsNone(resp.json()["brief"])
|
||||
|
||||
|
||||
class MySeaInviteAcceptDeclineTest(TestCase):
|
||||
def setUp(self):
|
||||
self.owner = User.objects.create(email="owner@test.io", username="discoman")
|
||||
self.bud = User.objects.create(email="bud@test.io", username="budster")
|
||||
self.invite = SeaInvite.objects.create(
|
||||
owner=self.owner, invitee=self.bud, invitee_email=self.bud.email,
|
||||
)
|
||||
log_sea_invite(self.invite)
|
||||
self.invite.refresh_from_db()
|
||||
|
||||
def test_invitee_accept_flips_to_accepted(self):
|
||||
self.client.force_login(self.bud)
|
||||
resp = self.client.post(
|
||||
reverse("my_sea_invite_accept", args=[self.invite.id])
|
||||
)
|
||||
self.invite.refresh_from_db()
|
||||
self.assertEqual(self.invite.status, SeaInvite.ACCEPTED)
|
||||
self.assertIsNotNone(self.invite.accepted_at)
|
||||
self.assertEqual(self.invite.invitee, self.bud)
|
||||
self.assertEqual(resp.status_code, 302)
|
||||
|
||||
def test_non_invitee_cannot_accept(self):
|
||||
stranger = User.objects.create(email="x@test.io", username="x")
|
||||
self.client.force_login(stranger)
|
||||
resp = self.client.post(
|
||||
reverse("my_sea_invite_accept", args=[self.invite.id])
|
||||
)
|
||||
self.invite.refresh_from_db()
|
||||
self.assertEqual(self.invite.status, SeaInvite.PENDING)
|
||||
self.assertEqual(resp.status_code, 403)
|
||||
|
||||
def test_invitee_decline_flips_to_declined(self):
|
||||
self.client.force_login(self.bud)
|
||||
self.client.post(reverse("my_sea_invite_decline", args=[self.invite.id]))
|
||||
self.invite.refresh_from_db()
|
||||
self.assertEqual(self.invite.status, SeaInvite.DECLINED)
|
||||
|
||||
def test_non_invitee_cannot_decline(self):
|
||||
stranger = User.objects.create(email="x@test.io", username="x")
|
||||
self.client.force_login(stranger)
|
||||
resp = self.client.post(
|
||||
reverse("my_sea_invite_decline", args=[self.invite.id])
|
||||
)
|
||||
self.invite.refresh_from_db()
|
||||
self.assertEqual(self.invite.status, SeaInvite.PENDING)
|
||||
self.assertEqual(resp.status_code, 403)
|
||||
|
||||
def test_expired_invite_cannot_be_accepted(self):
|
||||
SeaInvite.objects.filter(pk=self.invite.pk).update(
|
||||
created_at=timezone.now() - timedelta(hours=25)
|
||||
)
|
||||
self.client.force_login(self.bud)
|
||||
self.client.post(reverse("my_sea_invite_accept", args=[self.invite.id]))
|
||||
self.invite.refresh_from_db()
|
||||
self.assertEqual(self.invite.status, SeaInvite.PENDING) # unchanged
|
||||
|
||||
|
||||
class MySeaInvitePostRenderTest(TestCase):
|
||||
"""post.html — the @mailman invite Line carries a post-attribution
|
||||
anchor around the owner's handle whose href routes to the owner's
|
||||
@@ -154,16 +95,15 @@ class MySeaInvitePostRenderTest(TestCase):
|
||||
self.invite.refresh_from_db()
|
||||
self.client.force_login(self.bud)
|
||||
self.post_url = reverse("billboard:view_post", args=[self.post.id])
|
||||
self.accept_url = reverse("my_sea_invite_accept", args=[self.invite.id])
|
||||
self.decline_url = reverse("my_sea_invite_decline", args=[self.invite.id])
|
||||
|
||||
def test_pending_invite_renders_post_attribution_anchor_not_buttons(self):
|
||||
content = self.client.get(self.post_url).content.decode()
|
||||
# OK/BYE buttons + accept/decline form actions migrated onto bud.html.
|
||||
# OK/BYE buttons + the accept/decline form actions are gone entirely.
|
||||
self.assertNotIn("invite-ok-btn", content)
|
||||
self.assertNotIn("invite-bye-btn", content)
|
||||
self.assertNotIn(self.accept_url, content)
|
||||
self.assertNotIn(self.decline_url, content)
|
||||
self.assertNotIn("invite-action-form", content)
|
||||
self.assertNotIn("my-sea/invite/accept", content)
|
||||
self.assertNotIn("my-sea/invite/decline", content)
|
||||
# Anchor wraps the owner's handle, routing to their bud landing page.
|
||||
self.assertIn('class="post-attribution"', content)
|
||||
self.assertIn(f"/billboard/buds/{self.owner.id}/", content)
|
||||
@@ -175,14 +115,14 @@ class MySeaInvitePostRenderTest(TestCase):
|
||||
content = self.client.get(self.post_url).content.decode()
|
||||
# No "Accepted <date>" badge — the sweep is unconditional.
|
||||
self.assertNotIn("invite-badge--accepted", content)
|
||||
self.assertNotIn(self.accept_url, content)
|
||||
self.assertNotIn("invite-action-form", content)
|
||||
|
||||
def test_declined_invite_renders_no_badge(self):
|
||||
self.invite.status = SeaInvite.DECLINED
|
||||
self.invite.save()
|
||||
content = self.client.get(self.post_url).content.decode()
|
||||
self.assertNotIn("invite-badge--declined", content)
|
||||
self.assertNotIn(self.accept_url, content)
|
||||
self.assertNotIn("invite-action-form", content)
|
||||
|
||||
def test_mailman_line_renders_as_system_with_handles(self):
|
||||
content = self.client.get(self.post_url).content.decode()
|
||||
|
||||
Reference in New Issue
Block a user