From ab35221724b0ed23cb8c1b6d1a0300e3fd05ffc1 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Wed, 8 Nov 2023 12:11:20 -0600 Subject: [PATCH 1/4] Send domain invitations to particular email addresses, tests don't work --- .../commands/send_domain_invitations.py | 22 +++++++++++++++---- .../test_transition_domain_migrations.py | 21 ++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/registrar/management/commands/send_domain_invitations.py b/src/registrar/management/commands/send_domain_invitations.py index f6abb3cf0..a2a9475e0 100644 --- a/src/registrar/management/commands/send_domain_invitations.py +++ b/src/registrar/management/commands/send_domain_invitations.py @@ -37,14 +37,28 @@ class Command(BaseCommand): help="Send emails ", ) + parser.add_argument( + "emails", + nargs="*", + help="Email addresses to send invitations to" + ) + def handle(self, **options): """Process the objects in TransitionDomain.""" logger.info("checking domains and preparing emails") - # Get all TransitionDomain objects - self.transition_domains = TransitionDomain.objects.filter( - email_sent=False, - ).order_by("username") + + if options["emails"]: + # this option is a list of email addresses + self.transition_domains = TransitionDomain.objects.filter( + username__in=options["emails"], + email_sent=False, + ).order_by("username") + else: + # Get all TransitionDomain objects + self.transition_domains = TransitionDomain.objects.filter( + email_sent=False, + ).order_by("username") logger.info("Found %d transition domains", len(self.transition_domains)) self.build_emails_to_send_array() diff --git a/src/registrar/tests/test_transition_domain_migrations.py b/src/registrar/tests/test_transition_domain_migrations.py index 11324cb37..7fd243073 100644 --- a/src/registrar/tests/test_transition_domain_migrations.py +++ b/src/registrar/tests/test_transition_domain_migrations.py @@ -1,3 +1,5 @@ +from io import StringIO + from django.test import TestCase from registrar.models import ( @@ -11,6 +13,8 @@ from registrar.models import ( from django.core.management import call_command +from .common import less_console_noise + class TestLogins(TestCase): @@ -259,3 +263,20 @@ class TestLogins(TestCase): expected_missing_domain_informations, expected_missing_domain_invitations, ) + + def test_send_domain_invitations_email(self): + """Can send only a single domain invitation email.""" + with less_console_noise(): + self.run_load_domains() + self.run_transfer_domains() + + # this is one of the email addresses in data/test_contacts.txt + output_stream = StringIO() + call_command("send_domain_invitations", + stdout=output_stream) + + # Check that we had the right numbers in our output + output = output_stream.getvalue() + print("Output:", output) + self.assertIn("Found 1 transition domains", output) + self.assertTrue("would send email to testuser@gmail.com", output) From a7804b35ea7cc8f923cb6fcacdbdef27b5ffd958 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Thu, 9 Nov 2023 15:39:53 -0600 Subject: [PATCH 2/4] Fix test case for sending invitations by email --- src/registrar/tests/common.py | 16 +++++++++++----- .../tests/test_transition_domain_migrations.py | 7 ++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/registrar/tests/common.py b/src/registrar/tests/common.py index ad464bb3e..6bcd3e15f 100644 --- a/src/registrar/tests/common.py +++ b/src/registrar/tests/common.py @@ -58,7 +58,7 @@ def get_handlers(): @contextmanager -def less_console_noise(): +def less_console_noise(output_stream=None): """ Context manager to use in tests to silence console logging. @@ -66,14 +66,19 @@ def less_console_noise(): (such as errors) which are normal and expected. It can easily be removed to debug a failing test. + + Arguments: + `output_stream`: a stream to redirect every handler to. If it's + not provided, use /dev/null. """ restore = {} handlers = get_handlers() - devnull = open(os.devnull, "w") + if output_stream is None: + output_stream = open(os.devnull, "w") # redirect all the streams for handler in handlers.values(): - prior = handler.setStream(devnull) + prior = handler.setStream(output_stream) restore[handler.name] = prior try: # run the test @@ -82,8 +87,9 @@ def less_console_noise(): # restore the streams for handler in handlers.values(): handler.setStream(restore[handler.name]) - # close the file we opened - devnull.close() + if output_stream is None: + # we opened output_stream so we have to close it + output_stream.close() class MockUserLogin: diff --git a/src/registrar/tests/test_transition_domain_migrations.py b/src/registrar/tests/test_transition_domain_migrations.py index 7fd243073..c33f9ff57 100644 --- a/src/registrar/tests/test_transition_domain_migrations.py +++ b/src/registrar/tests/test_transition_domain_migrations.py @@ -272,11 +272,12 @@ class TestLogins(TestCase): # this is one of the email addresses in data/test_contacts.txt output_stream = StringIO() - call_command("send_domain_invitations", - stdout=output_stream) + # also have to re-point the logging handlers to output_stream + with less_console_noise(output_stream): + call_command("send_domain_invitations", "testuser@gmail.com", stdout=output_stream) # Check that we had the right numbers in our output output = output_stream.getvalue() - print("Output:", output) + # should only be one domain we send email for self.assertIn("Found 1 transition domains", output) self.assertTrue("would send email to testuser@gmail.com", output) From 0e4ba770bf5a440b2f0c6c289bacd448c0a14580 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Thu, 9 Nov 2023 15:42:55 -0600 Subject: [PATCH 3/4] Add a test case for sending to multiple emails --- .../test_transition_domain_migrations.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/registrar/tests/test_transition_domain_migrations.py b/src/registrar/tests/test_transition_domain_migrations.py index c33f9ff57..27264c54e 100644 --- a/src/registrar/tests/test_transition_domain_migrations.py +++ b/src/registrar/tests/test_transition_domain_migrations.py @@ -281,3 +281,23 @@ class TestLogins(TestCase): # should only be one domain we send email for self.assertIn("Found 1 transition domains", output) self.assertTrue("would send email to testuser@gmail.com", output) + + def test_send_domain_invitations_two_emails(self): + """Can send only a single domain invitation email.""" + with less_console_noise(): + self.run_load_domains() + self.run_transfer_domains() + + # these are two email addresses in data/test_contacts.txt + output_stream = StringIO() + # also have to re-point the logging handlers to output_stream + with less_console_noise(output_stream): + call_command("send_domain_invitations", "testuser@gmail.com", + "agustina.wyman7@test.com", stdout=output_stream) + + # Check that we had the right numbers in our output + output = output_stream.getvalue() + # should only be one domain we send email for + self.assertIn("Found 2 transition domains", output) + self.assertTrue("would send email to testuser@gmail.com", output) + self.assertTrue("would send email to agustina.wyman7@test.com", output) From 7b69df29bde80e685cf0d2a9418fa7c4a247d4c2 Mon Sep 17 00:00:00 2001 From: Neil Martinsen-Burrell Date: Mon, 13 Nov 2023 09:40:21 -0600 Subject: [PATCH 4/4] Long line linting --- .../management/commands/send_domain_invitations.py | 6 +----- src/registrar/tests/test_transition_domain_migrations.py | 5 +++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/registrar/management/commands/send_domain_invitations.py b/src/registrar/management/commands/send_domain_invitations.py index e546a4b76..68e805be9 100644 --- a/src/registrar/management/commands/send_domain_invitations.py +++ b/src/registrar/management/commands/send_domain_invitations.py @@ -37,11 +37,7 @@ class Command(BaseCommand): help="Send emails ", ) - parser.add_argument( - "emails", - nargs="*", - help="Email addresses to send invitations to" - ) + parser.add_argument("emails", nargs="*", help="Email addresses to send invitations to") def handle(self, **options): """Process the objects in TransitionDomain.""" diff --git a/src/registrar/tests/test_transition_domain_migrations.py b/src/registrar/tests/test_transition_domain_migrations.py index 3a1811cb9..edc8c8563 100644 --- a/src/registrar/tests/test_transition_domain_migrations.py +++ b/src/registrar/tests/test_transition_domain_migrations.py @@ -284,8 +284,9 @@ class TestLogins(TestCase): output_stream = StringIO() # also have to re-point the logging handlers to output_stream with less_console_noise(output_stream): - call_command("send_domain_invitations", "testuser@gmail.com", - "agustina.wyman7@test.com", stdout=output_stream) + call_command( + "send_domain_invitations", "testuser@gmail.com", "agustina.wyman7@test.com", stdout=output_stream + ) # Check that we had the right numbers in our output output = output_stream.getvalue()