From cea60ad8dfe1499451ffdd8771079de1c2c7a5c6 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Sun, 28 Sep 2014 18:59:10 +0000 Subject: [PATCH] Merged in [8255] from rjsparks@nostrum.com:\n Combined defer/undefer tests from doc/tests_ballot and iesg/tests, extending them to demonstrate current reported bugs. Made doc.active_defer_event() look for the events that are currently being created. This remains brittle. Added email notifying the IESG of an undefer analagous to the defer email. Guarded against deferring an already deferred document or undeferring a document that hasn't been deferred. Guarded against deferring a document that's not scheduled for a telechat. Fixes bugs 1417, 1465, 1417 - Legacy-Id: 8366 Note: SVN reference [8255] has been migrated to Git commit 0b49f402b4ec9145cb290b8a968755cc9ebdef92 --- ietf/doc/mails.py | 12 ++ ietf/doc/models.py | 4 +- ietf/doc/tests_ballot.py | 173 +++++++++++++----- ietf/doc/views_ballot.py | 15 +- ietf/iesg/tests.py | 96 ---------- .../doc/document_ballot_content.html | 4 +- .../doc/mail/ballot_deferred_email.txt | 2 +- 7 files changed, 155 insertions(+), 151 deletions(-) diff --git a/ietf/doc/mails.py b/ietf/doc/mails.py index f29cf03f1..2e3fe3266 100644 --- a/ietf/doc/mails.py +++ b/ietf/doc/mails.py @@ -311,6 +311,18 @@ def email_ballot_deferred(request, doc, by, telechat_date): "doc/mail/ballot_deferred_email.txt", dict(doc=doc, by=by, + action='deferred', + telechat_date=telechat_date)) + +def email_ballot_undeferred(request, doc, by, telechat_date): + to = "iesg@ietf.org" + frm = "DraftTracker Mail System " + send_mail(request, to, frm, + "IESG Undeferred Ballot notification: %s" % doc.file_tag(), + "doc/mail/ballot_deferred_email.txt", + dict(doc=doc, + by=by, + action='undeferred', telechat_date=telechat_date)) def generate_issue_ballot_mail(request, doc, ballot): diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 8fd884866..743c24685 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -387,9 +387,9 @@ class Document(DocumentInfo): # isn't this just returning whether the state is currently a defer state for that document type? def active_defer_event(self): if self.type_id == "draft" and self.get_state_slug("draft-iesg") == "defer": - return self.latest_event(type="changed_document", desc__startswith="State changed to IESG Evaluation - Defer") + return self.latest_event(type="changed_state", desc__icontains="State changed to IESG Evaluation - Defer") elif self.type_id == "conflrev" and self.get_state_slug("conflrev") == "defer": - return self.latest_event(type="changed_document", desc__startswith="State changed to IESG Evaluation - Defer") + return self.latest_event(type="changed_state", desc__icontains="State changed to IESG Evaluation - Defer") return None def most_recent_ietflc(self): diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py index 2934b4db0..b95a29c40 100644 --- a/ietf/doc/tests_ballot.py +++ b/ietf/doc/tests_ballot.py @@ -6,9 +6,10 @@ import debug # pyflakes:ignore from django.core.urlresolvers import reverse as urlreverse from ietf.doc.models import ( Document, State, DocEvent, BallotDocEvent, - BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent ) + BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent, TelechatDocEvent ) from ietf.group.models import Group, Role from ietf.name.models import BallotPositionName +from ietf.iesg.models import TelechatDate from ietf.person.models import Person from ietf.utils.test_utils import TestCase from ietf.utils.mail import outbox @@ -162,52 +163,6 @@ class EditPositionTests(TestCase): self.assertTrue("clearer title" in str(m)) self.assertTrue("Test!" in str(m)) - -class DeferBallotTests(TestCase): - def test_defer_ballot(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) - - url = urlreverse('doc_defer_ballot', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "ad", url) - - # normal get - r = self.client.get(url) - self.assertEqual(r.status_code, 200) - - # defer - mailbox_before = len(outbox) - - r = self.client.post(url, dict()) - self.assertEqual(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEqual(draft.get_state_slug("draft-iesg"), "defer") - - self.assertEqual(len(outbox), mailbox_before + 2) - self.assertTrue("State Update" in outbox[-2]['Subject']) - self.assertTrue("Deferred" in outbox[-1]['Subject']) - self.assertTrue(draft.file_tag() in outbox[-1]['Subject']) - - def test_undefer_ballot(self): - draft = make_test_data() - draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="defer")) - - url = urlreverse('doc_undefer_ballot', kwargs=dict(name=draft.name)) - login_testing_unauthorized(self, "ad", url) - - # normal get - r = self.client.get(url) - self.assertEqual(r.status_code, 200) - - # undefer - r = self.client.post(url, dict()) - self.assertEqual(r.status_code, 302) - - draft = Document.objects.get(name=draft.name) - self.assertEqual(draft.get_state_slug("draft-iesg"), "iesg-eva") - - class BallotWriteupsTests(TestCase): def test_edit_last_call_text(self): draft = make_test_data() @@ -482,3 +437,127 @@ class MakeLastCallTests(TestCase): self.assertTrue("Last Call" in outbox[-3]['Subject']) self.assertTrue("Last Call" in draft.message_set.order_by("-time")[0].subject) +class DeferUndeferTestCase(TestCase): + def helper_test_defer(self,name): + + doc = Document.objects.get(name=name) + url = urlreverse('doc_defer_ballot',kwargs=dict(name=doc.name)) + + login_testing_unauthorized(self, "ad", url) + + # Verify that you can't defer a document that's not on a telechat + r = self.client.post(url,dict()) + self.assertEqual(r.status_code, 404) + + # Put the document on a telechat + dates = TelechatDate.objects.active().order_by("date") + first_date = dates[0].date + second_date = dates[1].date + + e = TelechatDocEvent(type="scheduled_for_telechat", + doc = doc, + by = Person.objects.get(name="Aread Irector"), + telechat_date = first_date, + returning_item = False, + ) + e.save() + + # get + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + q = PyQuery(r.content) + self.assertEqual(len(q('form.defer')),1) + + # defer + mailbox_before = len(outbox) + self.assertEqual(doc.telechat_date(), first_date) + r = self.client.post(url,dict()) + self.assertEqual(r.status_code, 302) + doc = Document.objects.get(name=name) + self.assertEqual(doc.telechat_date(), second_date) + self.assertTrue(doc.returning_item()) + defer_states = dict(draft=['draft-iesg','defer'],conflrev=['conflrev','defer']) + if doc.type_id in defer_states: + self.assertEqual(doc.get_state(defer_states[doc.type_id][0]).slug,defer_states[doc.type_id][1]) + self.assertTrue(doc.active_defer_event()) + self.assertEqual(len(outbox), mailbox_before + 2) + self.assertTrue("State Update" in outbox[-2]['Subject']) + self.assertTrue("Deferred" in outbox[-1]['Subject']) + self.assertTrue(doc.file_tag() in outbox[-1]['Subject']) + + # Ensure it's not possible to defer again + r = self.client.get(url) + self.assertEqual(r.status_code, 404) + r = self.client.post(url,dict()) + self.assertEqual(r.status_code, 404) + + + def helper_test_undefer(self,name): + + doc = Document.objects.get(name=name) + url = urlreverse('doc_undefer_ballot',kwargs=dict(name=doc.name)) + + login_testing_unauthorized(self, "ad", url) + + # some additional setup + dates = TelechatDate.objects.active().order_by("date") + first_date = dates[0].date + second_date = dates[1].date + + e = TelechatDocEvent(type="scheduled_for_telechat", + doc = doc, + by = Person.objects.get(name="Aread Irector"), + telechat_date = second_date, + returning_item = True, + ) + e.save() + defer_states = dict(draft=['draft-iesg','defer'],conflrev=['conflrev','defer']) + if doc.type_id in defer_states: + doc.set_state(State.objects.get(used=True, type=defer_states[doc.type_id][0],slug=defer_states[doc.type_id][1])) + doc.save() + + # get + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + q = PyQuery(r.content) + self.assertEqual(len(q('form.undefer')),1) + + # undefer + mailbox_before = len(outbox) + self.assertEqual(doc.telechat_date(), second_date) + r = self.client.post(url,dict()) + self.assertEqual(r.status_code, 302) + doc = Document.objects.get(name=name) + self.assertEqual(doc.telechat_date(), first_date) + self.assertTrue(doc.returning_item()) + undefer_states = dict(draft=['draft-iesg','iesg-eva'],conflrev=['conflrev','iesgeval']) + if doc.type_id in undefer_states: + self.assertEqual(doc.get_state(undefer_states[doc.type_id][0]).slug,undefer_states[doc.type_id][1]) + self.assertFalse(doc.active_defer_event()) + self.assertEqual(len(outbox), mailbox_before + 2) + self.assertTrue("State Update" in outbox[-2]['Subject']) + self.assertTrue("Undeferred" in outbox[-1]['Subject']) + self.assertTrue(doc.file_tag() in outbox[-1]['Subject']) + + # Ensure it's not possible to undefer again + r = self.client.get(url) + self.assertEqual(r.status_code, 404) + r = self.client.post(url,dict()) + self.assertEqual(r.status_code, 404) + + def test_defer_draft(self): + self.helper_test_defer('draft-ietf-mars-test') + + def test_defer_conflict_review(self): + self.helper_test_defer('conflict-review-imaginary-irtf-submission') + + def test_undefer_draft(self): + self.helper_test_undefer('draft-ietf-mars-test') + + def test_undefer_conflict_review(self): + self.helper_test_undefer('conflict-review-imaginary-irtf-submission') + + # when charters support being deferred, be sure to test them here + + def setUp(self): + make_test_data() diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py index c347aedce..cf20d40af 100644 --- a/ietf/doc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -17,9 +17,9 @@ from ietf.doc.models import ( Document, State, DocEvent, BallotDocEvent, BallotP BallotType, LastCallDocEvent, WriteupDocEvent, save_document_in_history, IESG_SUBSTATE_TAGS ) from ietf.doc.utils import ( add_state_change_event, close_ballot, close_open_ballots, create_ballot_if_not_open, update_telechat ) -from ietf.doc.mails import ( email_ad, email_ballot_deferred, email_state_changed, - extra_automation_headers, generate_last_call_announcement, generate_issue_ballot_mail, - generate_ballot_writeup, generate_approval_mail ) +from ietf.doc.mails import ( email_ad, email_ballot_deferred, email_ballot_undeferred, + email_state_changed, extra_automation_headers, generate_last_call_announcement, + generate_issue_ballot_mail, generate_ballot_writeup, generate_approval_mail ) from ietf.doc.lastcall import request_last_call from ietf.iesg.models import TelechatDate from ietf.ietfauth.utils import has_role, role_required @@ -69,6 +69,7 @@ def do_undefer_ballot(request, doc): update_telechat(request, doc, login, telechat_date) email_state_changed(request, doc, e.desc) + email_ballot_undeferred(request, doc, login.plain_name(), telechat_date) def position_to_ballot_choice(position): for v, label in BALLOT_CHOICES: @@ -335,7 +336,9 @@ def defer_ballot(request, name): doc = get_object_or_404(Document, docalias__name=name) if doc.type_id not in ('draft','conflrev'): raise Http404() - if doc.type_id == 'draft' and not doc.get_state("draft-iesg"): + interesting_state = dict(draft='draft-iesg',conflrev='conflrev') + state = doc.get_state(interesting_state[doc.type_id]) + if not state or state.slug=='defer' or not doc.telechat_date(): raise Http404() login = request.user.person @@ -384,6 +387,10 @@ def undefer_ballot(request, name): raise Http404() if doc.type_id == 'draft' and not doc.get_state("draft-iesg"): raise Http404() + interesting_state = dict(draft='draft-iesg',conflrev='conflrev') + state = doc.get_state(interesting_state[doc.type_id]) + if not state or state.slug!='defer': + raise Http404() telechat_date = TelechatDate.objects.active().order_by("date")[0].date diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py index be64c6553..5de7f6537 100644 --- a/ietf/iesg/tests.py +++ b/ietf/iesg/tests.py @@ -442,99 +442,3 @@ class RescheduleOnAgendaTests(TestCase): self.assertTrue(not draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").returning_item) self.assertEqual(draft.docevent_set.count(), events_before + 1) -class DeferUndeferTestCase(TestCase): - def helper_test_defer(self,name): - - doc = Document.objects.get(name=name) - url = urlreverse('doc_defer_ballot',kwargs=dict(name=doc.name)) - - login_testing_unauthorized(self, "ad", url) - - # some additional setup - dates = TelechatDate.objects.active().order_by("date") - first_date = dates[0].date - second_date = dates[1].date - - e = TelechatDocEvent(type="scheduled_for_telechat", - doc = doc, - by = Person.objects.get(name="Aread Irector"), - telechat_date = first_date, - returning_item = False, - ) - e.save() - - # get - r = self.client.get(url) - self.assertEqual(r.status_code, 200) - q = PyQuery(r.content) - self.assertEqual(len(q('form.defer')),1) - - # defer - self.assertEqual(doc.telechat_date(), first_date) - r = self.client.post(url,dict()) - self.assertEqual(r.status_code, 302) - doc = Document.objects.get(name=name) - self.assertEqual(doc.telechat_date(), second_date) - self.assertTrue(doc.returning_item()) - defer_states = dict(draft=['draft-iesg','defer'],conflrev=['conflrev','defer']) - if doc.type_id in defer_states: - self.assertEqual(doc.get_state(defer_states[doc.type_id][0]).slug,defer_states[doc.type_id][1]) - - - def helper_test_undefer(self,name): - - doc = Document.objects.get(name=name) - url = urlreverse('doc_undefer_ballot',kwargs=dict(name=doc.name)) - - login_testing_unauthorized(self, "ad", url) - - # some additional setup - dates = TelechatDate.objects.active().order_by("date") - first_date = dates[0].date - second_date = dates[1].date - - e = TelechatDocEvent(type="scheduled_for_telechat", - doc = doc, - by = Person.objects.get(name="Aread Irector"), - telechat_date = second_date, - returning_item = True, - ) - e.save() - defer_states = dict(draft=['draft-iesg','defer'],conflrev=['conflrev','defer']) - if doc.type_id in defer_states: - doc.set_state(State.objects.get(used=True, type=defer_states[doc.type_id][0],slug=defer_states[doc.type_id][1])) - doc.save() - - # get - r = self.client.get(url) - self.assertEqual(r.status_code, 200) - q = PyQuery(r.content) - self.assertEqual(len(q('form.undefer')),1) - - # undefer - self.assertEqual(doc.telechat_date(), second_date) - r = self.client.post(url,dict()) - self.assertEqual(r.status_code, 302) - doc = Document.objects.get(name=name) - self.assertEqual(doc.telechat_date(), first_date) - self.assertTrue(doc.returning_item()) - undefer_states = dict(draft=['draft-iesg','iesg-eva'],conflrev=['conflrev','iesgeval']) - if doc.type_id in undefer_states: - self.assertEqual(doc.get_state(undefer_states[doc.type_id][0]).slug,undefer_states[doc.type_id][1]) - - def test_defer_draft(self): - self.helper_test_defer('draft-ietf-mars-test') - - def test_defer_conflict_review(self): - self.helper_test_defer('conflict-review-imaginary-irtf-submission') - - def test_undefer_draft(self): - self.helper_test_undefer('draft-ietf-mars-test') - - def test_undefer_conflict_review(self): - self.helper_test_undefer('conflict-review-imaginary-irtf-submission') - - # when charters support being deferred, be sure to test them here - - def setUp(self): - make_test_data() diff --git a/ietf/templates/doc/document_ballot_content.html b/ietf/templates/doc/document_ballot_content.html index df61975a7..b7acc5884 100644 --- a/ietf/templates/doc/document_ballot_content.html +++ b/ietf/templates/doc/document_ballot_content.html @@ -13,7 +13,9 @@
Undefer ballot
Ballot deferred by {{ deferred.by }} on {{ deferred.time|date:"Y-m-d" }}.
{% else %} -
Defer ballot
+ {% if doc.telechat_date %} +
Defer ballot
+ {% endif %} {% endif %} {% if user|has_role:"Secretariat" %}
Clear ballot
diff --git a/ietf/templates/doc/mail/ballot_deferred_email.txt b/ietf/templates/doc/mail/ballot_deferred_email.txt index f08daa201..53c9c39d1 100644 --- a/ietf/templates/doc/mail/ballot_deferred_email.txt +++ b/ietf/templates/doc/mail/ballot_deferred_email.txt @@ -1,4 +1,4 @@ -{% autoescape off %}{% filter wordwrap:73 %}Ballot of {{ doc.file_tag }} has been deferred by {{ by }}.{% endfilter %} +{% autoescape off %}{% filter wordwrap:73 %}Ballot of {{ doc.file_tag }} has been {{action}} by {{ by }}.{% endfilter %} This ballot will be on the IESG agenda of {{ telechat_date }}. {% endautoescape %}