Repository: ietf-tools/datatracker

Issue:
test_docs_for_ad randomly spuriously fails
We occasionally see this failure:
 ======================================================================
FAIL: test_docs_for_ad (ietf.doc.tests.SearchTests.test_docs_for_ad)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/__w/datatracker/datatracker/ietf/doc/tests.py", line 301, in test_docs_for_ad
    self.assertEqual(r.status_code, 200)
AssertionError: 404 != 200

It's clearly a test-harness randomly generated data data mismatch with the view being tested. Investigation is needed to see if this is a real (but obscure corner) bug, or just insufficient constraints on the generated data issue. 


Discussion:
I was very sure it would fail with `person__name="O'Gowan Mullin"` but no luck.

Resolving patch:
diff --git a/ietf/person/factories.py b/ietf/person/factories.py
--- a/ietf/person/factories.py
+++ b/ietf/person/factories.py
@@ -11,6 +11,7 @@
 import shutil
 
 from unidecode import unidecode
+from unicodedata import normalize
 
 from django.conf import settings
 from django.contrib.auth.models import User
@@ -47,8 +48,9 @@ class Meta:
         exclude = ['faker', ]
 
     faker = factory.LazyFunction(random_faker)
-    first_name = factory.LazyAttribute(lambda o: o.faker.first_name())
-    last_name = factory.LazyAttribute(lambda o: o.faker.last_name())
+    # normalize these i18n Unicode strings in the same way the database does
+    first_name = factory.LazyAttribute(lambda o: normalize("NFKC", o.faker.first_name()))
+    last_name = factory.LazyAttribute(lambda o: normalize("NFKC", o.faker.last_name()))
     email = factory.LazyAttributeSequence(lambda u, n: '%s.%s_%d@%s'%( slugify(unidecode(u.first_name)),
                                                 slugify(unidecode(u.last_name)), n, fake.domain_name())) # type: ignore
     username = factory.LazyAttribute(lambda u: u.email)


Test patch:
diff --git a/ietf/doc/tests_review.py b/ietf/doc/tests_review.py
--- a/ietf/doc/tests_review.py
+++ b/ietf/doc/tests_review.py
@@ -414,7 +414,7 @@ def test_reject_reviewer_assignment(self):
         login_testing_unauthorized(self, "reviewsecretary", reject_url)
         r = self.client.get(reject_url)
         self.assertEqual(r.status_code, 200)
-        self.assertContains(r, assignment.reviewer.person.name)
+        self.assertContains(r, escape(assignment.reviewer.person.name))
         self.assertNotContains(r, 'can not be rejected')
         self.assertContains(r, '<button type="submit"')
 
@@ -442,7 +442,7 @@ def test_reject_reviewer_assignment(self):
         
         r = self.client.get(reject_url)
         self.assertEqual(r.status_code, 200)
-        self.assertContains(r, assignment.reviewer.person.name)
+        self.assertContains(r, escape(assignment.reviewer.person.name))
         self.assertContains(r, 'can not be rejected')
         self.assertNotContains(r, '<button type="submit"')
 
@@ -1154,4 +1154,4 @@ def test_review_wishes_remove(self):
         ReviewWish.objects.create(person=reviewer, doc=doc, team=team)
         r = self.client.post(url + '?next=http://example.com')
         self.assertRedirects(r, doc.get_absolute_url(), fetch_redirect_response=False)
-        self.assertFalse(ReviewWish.objects.all())
\ No newline at end of file
+        self.assertFalse(ReviewWish.objects.all())
diff --git a/ietf/review/tests.py b/ietf/review/tests.py
--- a/ietf/review/tests.py
+++ b/ietf/review/tests.py
@@ -384,10 +384,10 @@ def test_send_unavailability_period_ending_reminder(self):
         self.assertTrue(self.reviewer.email_address() in outbox[0]["To"])
         self.assertTrue(secretary.person.email_address() in outbox[0]["To"])
         message = get_payload_text(outbox[0])
-        self.assertTrue(self.reviewer.name in message)
+        self.assertTrue(self.reviewer.plain_name() in message)
         self.assertTrue(self.team.acronym in message)
         self.assertEqual(len(log), 1)
-        self.assertTrue(self.reviewer.name in log[0])
+        self.assertTrue(self.reviewer.plain_name() in log[0])
         self.assertTrue(self.team.acronym in log[0])
 
     def test_send_review_reminder_overdue_assignment(self):