From 46f4e0292acbf39c6e3f33288eda8086f895674a Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 18 Jun 2026 09:53:26 +1200 Subject: [PATCH] fix: include URL to I-D Archive in WGLC messages --- ietf/doc/models.py | 5 ++++ ietf/doc/tests_draft.py | 53 ++++++++++++++++++++++++++++++++++++++++- ietf/doc/views_draft.py | 1 + 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 156bac4e77..f6e5e8241c 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -344,6 +344,11 @@ def _get_ref(self, meeting=None, versioned=True): setattr(self, cache_attr, href) return getattr(self, cache_attr) + def refresh_from_db(self, using=None, fields=None, **kwargs): + super().refresh_from_db(using=using, fields=fields, **kwargs) + self.state_cache = None + self._cached_state_slug = {} + def set_state(self, state): """Switch state type implicit in state to state. This just sets the state, doesn't log the change.""" diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index db9dbc2baf..688b933aad 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -2187,9 +2187,34 @@ def _assert_rejected(testcase, doc, person): chair = RoleFactory(name_id="chair", group=doc.group).person url = urlreverse("ietf.doc.views_draft.issue_wg_lc", kwargs=dict(name=doc.name)) login_testing_unauthorized(self, chair.user.username, url) + + # GET: check 200 and that the pre-populated body contains the archive URL r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) + prefilled_body = q("textarea#id_body").text() + expected_archive_url = f"{settings.IETF_ID_ARCHIVE_URL}{doc.name}-{doc.rev}.txt" + self.assertIn( + expected_archive_url, + prefilled_body, + "Pre-populated body must contain the I-D archive .txt URL", + ) + + # Invalid POST: end_date in the past must not change state + bad_postdict = dict( + end_date=date_today(DEADLINE_TZINFO), + to=q("input#id_to").attr("value"), + subject=q("input#id_subject").attr("value"), + body=prefilled_body, + ) + r = self.client.post(url, bad_postdict) + self.assertEqual(r.status_code, 200, "Invalid POST should re-render the form") + self.assertNotEqual( + doc.get_state_slug("draft-stream-ietf"), + "wg-lc", + "State must not change on invalid POST", + ) + postdict = dict() postdict["end_date"] = q("input#id_end_date").attr("value") postdict["to"] = q("input#id_to").attr("value") + ", extrato@example.org" @@ -2199,15 +2224,36 @@ def _assert_rejected(testcase, doc, person): else: postdict["cc"] = "extracc@example.org" postdict["subject"] = q("input#id_subject").attr("value") + " Extra Subject Words" - postdict["body"] = q("textarea#id_body").text() + "FGgqbQ$UNeXs" + postdict["body"] = prefilled_body + "FGgqbQ$UNeXs" empty_outbox() r = self.client.post( url, postdict, ) self.assertEqual(r.status_code, 302) + doc.refresh_from_db() self.assertEqual(doc.get_state_slug("draft-stream-ietf"), "wg-lc") + + # A StateDocEvent recording the transition must exist + self.assertTrue( + doc.docevent_set.filter(type="changed_state").exists(), + "Expected a changed_state event after issuing WG LC", + ) + + # A stream-s reminder must be active for the doc + self.assertTrue( + DocReminder.objects.filter( + event__doc=doc, type_id="stream-s", active=True + ).exists(), + "Expected an active stream-s reminder after issuing WG LC", + ) + self.assertEqual(len(outbox), 2) + + # outbox[0] is the stream-state-changed notification + self.assertIn(doc.name, outbox[0]["Subject"]) + + # outbox[1] is the WGLC announcement sent to the WG list self.assertIn(f"{doc.group.acronym}@ietf.org", outbox[1]["To"]) self.assertIn("extrato@example.org", outbox[1]["To"]) self.assertIn("extracc@example.org", outbox[1]["Cc"]) @@ -2216,6 +2262,11 @@ def _assert_rejected(testcase, doc, person): body = get_payload_text(outbox[1]) self.assertIn("disclosure obligations", body) self.assertIn("FGgqbQ$UNeXs", body) + self.assertIn( + expected_archive_url, + body, + "WGLC email body must contain the I-D archive .txt URL", + ) def test_issue_wg_call_for_adoption_form(self): end_date = date_today(DEADLINE_TZINFO) + datetime.timedelta(days=1) diff --git a/ietf/doc/views_draft.py b/ietf/doc/views_draft.py index 0f5ea49f5d..a64d0a53fe 100644 --- a/ietf/doc/views_draft.py +++ b/ietf/doc/views_draft.py @@ -1973,6 +1973,7 @@ def issue_wg_lc(request, name): doc=doc, end_date=end_date, wg_list=doc.group.list_email, + url=f"{settings.IETF_ID_ARCHIVE_URL}{doc.name}-{doc.rev}.txt", settings=settings, ), )