Skip to content

Commit a54894f

Browse files
JacobCoffeecodexclaude
committed
update tests for structured previous service and statement preview
Co-Authored-By: Codex <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 5a85763 commit a54894f

3 files changed

Lines changed: 89 additions & 11 deletions

File tree

apps/nominations/tests/test_forms.py

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
from apps.nominations.forms import (
66
BoardNominationCreateForm,
7+
NominationForm,
78
PackagingCouncilNominationCreateForm,
8-
PackagingCouncilNominationEditForm,
99
)
10-
from apps.nominations.models import Election
10+
from apps.nominations.models import Election, Nomination
1111
from apps.nominations.tests.utils import nomination_payload, packaging_council_kind
1212
from apps.users.factories import UserFactory
1313

@@ -55,6 +55,26 @@ def test_has_no_eligibility_field(self):
5555
self.assertNotIn("eligibility_confirmed", form.fields)
5656
self.assertEqual(form.acknowledgment_field_names, ("coc_acknowledged", "mission_alignment"))
5757

58+
def test_no_previous_service_stores_new_member(self):
59+
form = self._form(nomination_payload())
60+
self.assertTrue(form.is_valid(), form.errors)
61+
self.assertEqual(form.instance.previous_board_service, "New board member")
62+
63+
def test_previous_service_yes_requires_years(self):
64+
form = self._form(nomination_payload(previous_service="yes"))
65+
self.assertFalse(form.is_valid())
66+
self.assertIn("previous_service_years", form.errors)
67+
68+
def test_previous_service_years_compose_stored_value(self):
69+
form = self._form(nomination_payload(previous_service="yes", previous_service_years=["2021", "2019"]))
70+
self.assertTrue(form.is_valid(), form.errors)
71+
self.assertEqual(form.instance.previous_board_service, "2019, 2021")
72+
73+
def test_previous_service_years_reject_invalid_year(self):
74+
form = self._form(nomination_payload(previous_service="yes", previous_service_years=["1999"]))
75+
self.assertFalse(form.is_valid())
76+
self.assertIn("previous_service_years", form.errors)
77+
5878

5979
class PackagingCouncilNominationCreateFormTests(TestCase):
6080
def setUp(self):
@@ -91,7 +111,18 @@ def test_self_nomination_valid_with_both(self):
91111

92112
def test_previous_service_relabeled(self):
93113
form = self._form(nomination_payload())
94-
self.assertEqual(form.fields["previous_board_service"].label, "Previous Packaging Council Service")
114+
self.assertEqual(form.fields["previous_service"].label, "Previous Packaging Council Service")
115+
116+
def test_no_previous_service_stores_pc_new_member(self):
117+
form = self._form(nomination_payload())
118+
self.assertTrue(form.is_valid(), form.errors)
119+
self.assertEqual(form.instance.previous_board_service, "New Packaging Council member")
120+
121+
def test_pc_years_start_at_2025(self):
122+
form = self._form(nomination_payload())
123+
years = [choice for choice, _ in form.fields["previous_service_years"].choices]
124+
self.assertNotIn("2024", years)
125+
self.assertIn("2025", years)
95126

96127
def test_hide_previous_service_removes_field(self):
97128
election = Election.objects.create(
@@ -101,13 +132,14 @@ def test_hide_previous_service_removes_field(self):
101132
hide_previous_service=True,
102133
)
103134
data = nomination_payload()
104-
del data["previous_board_service"]
135+
del data["previous_service"]
105136
form = self._form(data, election=election)
106-
self.assertNotIn("previous_board_service", form.fields)
137+
self.assertNotIn("previous_service", form.fields)
138+
self.assertNotIn("previous_service_years", form.fields)
107139
self.assertTrue(form.is_valid(), form.errors)
108140

109141

110-
class PackagingCouncilNominationEditFormTests(TestCase):
142+
class NominationEditFormTests(TestCase):
111143
def setUp(self):
112144
self.kind = packaging_council_kind()
113145

@@ -120,9 +152,20 @@ def _election(self, **extra):
120152
)
121153

122154
def test_relabels_previous_service(self):
123-
form = PackagingCouncilNominationEditForm(election=self._election())
124-
self.assertEqual(form.fields["previous_board_service"].label, "Previous Packaging Council Service")
155+
form = NominationForm(election=self._election())
156+
self.assertEqual(form.fields["previous_service"].label, "Previous Packaging Council Service")
125157

126158
def test_hides_previous_service_when_opted_out(self):
127-
form = PackagingCouncilNominationEditForm(election=self._election(hide_previous_service=True))
128-
self.assertNotIn("previous_board_service", form.fields)
159+
form = NominationForm(election=self._election(hide_previous_service=True))
160+
self.assertNotIn("previous_service", form.fields)
161+
162+
def test_prefills_years_from_stored_free_text(self):
163+
nomination = Nomination(previous_board_service="Served 2025 and 2026")
164+
form = NominationForm(instance=nomination, election=self._election())
165+
self.assertEqual(form.fields["previous_service"].initial, "yes")
166+
self.assertEqual(form.fields["previous_service_years"].initial, ["2025", "2026"])
167+
168+
def test_prefills_no_from_stored_new_member(self):
169+
nomination = Nomination(previous_board_service="New Packaging Council member")
170+
form = NominationForm(instance=nomination, election=self._election())
171+
self.assertEqual(form.fields["previous_service"].initial, "no")

apps/nominations/tests/test_views.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,41 @@ def test_packaging_council_self_nomination_requires_eligibility(self):
116116
self.assertTrue(nomination.eligibility_confirmed)
117117

118118

119+
class NominationStatementPreviewTests(TestCase):
120+
def test_renders_markdown_with_html_escaped(self):
121+
self.client.force_login(UserFactory())
122+
response = self.client.post(
123+
reverse("nominations:nomination_preview"),
124+
{"text": "**bold** <script>alert(1)</script>"},
125+
)
126+
self.assertEqual(response.status_code, 200)
127+
html = response.json()["html"]
128+
self.assertIn("<strong>bold</strong>", html)
129+
self.assertNotIn("<script>", html)
130+
131+
def test_requires_login(self):
132+
response = self.client.post(reverse("nominations:nomination_preview"), {"text": "hi"})
133+
self.assertEqual(response.status_code, 302)
134+
135+
136+
class NominationPermissionTests(TestCase):
137+
def test_non_owner_gets_403_not_redirect_loop(self):
138+
owner = UserFactory(first_name="Nina", last_name="Nominator")
139+
other = UserFactory()
140+
election = open_election("2026 Board Election")
141+
nomination = Nomination.objects.create(
142+
election=election,
143+
nominator=owner,
144+
name="Grace Hopper",
145+
email="grace@example.com",
146+
nomination_statement="A strong candidate.",
147+
)
148+
self.client.force_login(other)
149+
url = reverse("nominations:nomination_edit", kwargs={"election": election.slug, "pk": nomination.pk})
150+
response = self.client.get(url)
151+
self.assertEqual(response.status_code, 403)
152+
153+
119154
class NominationEditVariantTests(TestCase):
120155
def setUp(self):
121156
self.user = UserFactory()

apps/nominations/tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def nomination_payload(**overrides):
3333
data = {
3434
"name": "Grace Hopper",
3535
"email": "grace@example.com",
36-
"previous_board_service": "New board member",
36+
"previous_service": "no",
3737
"employer": "US Navy",
3838
"other_affiliations": "",
3939
"nomination_statement": "A strong candidate.",

0 commit comments

Comments
 (0)