suppressed logging from all test cases; made slight changes to handling of exceptions in connection pooling

This commit is contained in:
David Kennedy 2024-01-29 18:22:35 -05:00
parent bf8d9159ce
commit 0546bd08e5
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
12 changed files with 3145 additions and 3166 deletions

View file

@ -35,6 +35,7 @@ class ViewsTest(TestCase):
pass pass
def test_openid_sets_next(self, mock_client): def test_openid_sets_next(self, mock_client):
with less_console_noise():
# setup # setup
callback_url = reverse("openid_login_callback") callback_url = reverse("openid_login_callback")
# mock # mock
@ -49,10 +50,10 @@ class ViewsTest(TestCase):
self.assertContains(response, "Hi") self.assertContains(response, "Hi")
def test_openid_raises(self, mock_client): def test_openid_raises(self, mock_client):
with less_console_noise():
# mock # mock
mock_client.create_authn_request.side_effect = Exception("Test") mock_client.create_authn_request.side_effect = Exception("Test")
# test # test
with less_console_noise():
response = self.client.get(reverse("login")) response = self.client.get(reverse("login"))
# assert # assert
self.assertEqual(response.status_code, 500) self.assertEqual(response.status_code, 500)
@ -62,17 +63,18 @@ class ViewsTest(TestCase):
def test_callback_with_no_session_state(self, mock_client): def test_callback_with_no_session_state(self, mock_client):
"""If the local session is None (ie the server restarted while user was logged out), """If the local session is None (ie the server restarted while user was logged out),
we do not throw an exception. Rather, we attempt to login again.""" we do not throw an exception. Rather, we attempt to login again."""
with less_console_noise():
# mock # mock
mock_client.get_default_acr_value.side_effect = self.create_acr mock_client.get_default_acr_value.side_effect = self.create_acr
mock_client.callback.side_effect = NoStateDefined() mock_client.callback.side_effect = NoStateDefined()
# test # test
with less_console_noise():
response = self.client.get(reverse("openid_login_callback")) response = self.client.get(reverse("openid_login_callback"))
# assert # assert
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/") self.assertEqual(response.url, "/")
def test_login_callback_reads_next(self, mock_client): def test_login_callback_reads_next(self, mock_client):
with less_console_noise():
# setup # setup
session = self.client.session session = self.client.session
session["next"] = reverse("logout") session["next"] = reverse("logout")
@ -89,6 +91,7 @@ class ViewsTest(TestCase):
def test_login_callback_no_step_up_auth(self, mock_client): def test_login_callback_no_step_up_auth(self, mock_client):
"""Walk through login_callback when requires_step_up_auth returns False """Walk through login_callback when requires_step_up_auth returns False
and assert that we have a redirect to /""" and assert that we have a redirect to /"""
with less_console_noise():
# setup # setup
session = self.client.session session = self.client.session
session.save() session.save()
@ -104,23 +107,20 @@ class ViewsTest(TestCase):
def test_requires_step_up_auth(self, mock_client): def test_requires_step_up_auth(self, mock_client):
"""Invoke login_callback passing it a request when requires_step_up_auth returns True """Invoke login_callback passing it a request when requires_step_up_auth returns True
and assert that session is updated and create_authn_request (mock) is called.""" and assert that session is updated and create_authn_request (mock) is called."""
with less_console_noise():
# Configure the mock to return an expected value for get_step_up_acr_value # Configure the mock to return an expected value for get_step_up_acr_value
mock_client.return_value.get_step_up_acr_value.return_value = "step_up_acr_value" mock_client.return_value.get_step_up_acr_value.return_value = "step_up_acr_value"
# Create a mock request # Create a mock request
request = self.factory.get("/some-url") request = self.factory.get("/some-url")
request.session = {"acr_value": ""} request.session = {"acr_value": ""}
# Ensure that the CLIENT instance used in login_callback is the mock # Ensure that the CLIENT instance used in login_callback is the mock
# patch requires_step_up_auth to return True # patch requires_step_up_auth to return True
with patch("djangooidc.views.requires_step_up_auth", return_value=True), patch( with patch("djangooidc.views.requires_step_up_auth", return_value=True), patch(
"djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock() "djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock()
) as mock_create_authn_request: ) as mock_create_authn_request:
login_callback(request) login_callback(request)
# create_authn_request only gets called when requires_step_up_auth is True # create_authn_request only gets called when requires_step_up_auth is True
# and it changes this acr_value in request.session # and it changes this acr_value in request.session
# Assert that acr_value is no longer empty string # Assert that acr_value is no longer empty string
self.assertNotEqual(request.session["acr_value"], "") self.assertNotEqual(request.session["acr_value"], "")
# And create_authn_request was called again # And create_authn_request was called again
@ -131,20 +131,18 @@ class ViewsTest(TestCase):
and assert that session is not updated and create_authn_request (mock) is not called. and assert that session is not updated and create_authn_request (mock) is not called.
Possibly redundant with test_login_callback_requires_step_up_auth""" Possibly redundant with test_login_callback_requires_step_up_auth"""
with less_console_noise():
# Create a mock request # Create a mock request
request = self.factory.get("/some-url") request = self.factory.get("/some-url")
request.session = {"acr_value": ""} request.session = {"acr_value": ""}
# Ensure that the CLIENT instance used in login_callback is the mock # Ensure that the CLIENT instance used in login_callback is the mock
# patch requires_step_up_auth to return False # patch requires_step_up_auth to return False
with patch("djangooidc.views.requires_step_up_auth", return_value=False), patch( with patch("djangooidc.views.requires_step_up_auth", return_value=False), patch(
"djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock() "djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock()
) as mock_create_authn_request: ) as mock_create_authn_request:
login_callback(request) login_callback(request)
# create_authn_request only gets called when requires_step_up_auth is True # create_authn_request only gets called when requires_step_up_auth is True
# and it changes this acr_value in request.session # and it changes this acr_value in request.session
# Assert that acr_value is NOT updated by testing that it is still an empty string # Assert that acr_value is NOT updated by testing that it is still an empty string
self.assertEqual(request.session["acr_value"], "") self.assertEqual(request.session["acr_value"], "")
# Assert create_authn_request was not called # Assert create_authn_request was not called
@ -152,6 +150,7 @@ class ViewsTest(TestCase):
@patch("djangooidc.views.authenticate") @patch("djangooidc.views.authenticate")
def test_login_callback_raises(self, mock_auth, mock_client): def test_login_callback_raises(self, mock_auth, mock_client):
with less_console_noise():
# mock # mock
mock_client.callback.side_effect = self.user_info mock_client.callback.side_effect = self.user_info
mock_auth.return_value = None mock_auth.return_value = None
@ -164,6 +163,7 @@ class ViewsTest(TestCase):
self.assertIn("Unauthorized", response.content.decode("utf-8")) self.assertIn("Unauthorized", response.content.decode("utf-8"))
def test_logout_redirect_url(self, mock_client): def test_logout_redirect_url(self, mock_client):
with less_console_noise():
# setup # setup
session = self.client.session session = self.client.session
session["state"] = "TEST" # nosec B105 session["state"] = "TEST" # nosec B105
@ -194,6 +194,7 @@ class ViewsTest(TestCase):
self.assertTrue(mock_logout.called) self.assertTrue(mock_logout.called)
def test_logout_callback_redirects(self, _): def test_logout_callback_redirects(self, _):
with less_console_noise():
# setup # setup
session = self.client.session session = self.client.session
session["next"] = reverse("logout") session["next"] = reverse("logout")

View file

@ -0,0 +1,51 @@
import os
import logging
from contextlib import contextmanager
def get_handlers():
"""Obtain pointers to all StreamHandlers."""
handlers = {}
rootlogger = logging.getLogger()
for h in rootlogger.handlers:
if isinstance(h, logging.StreamHandler):
handlers[h.name] = h
for logger in logging.Logger.manager.loggerDict.values():
if not isinstance(logger, logging.PlaceHolder):
for h in logger.handlers:
if isinstance(h, logging.StreamHandler):
handlers[h.name] = h
return handlers
@contextmanager
def less_console_noise():
"""
Context manager to use in tests to silence console logging.
This is helpful on tests which trigger console messages
(such as errors) which are normal and expected.
It can easily be removed to debug a failing test.
"""
restore = {}
handlers = get_handlers()
devnull = open(os.devnull, "w")
# redirect all the streams
for handler in handlers.values():
prior = handler.setStream(devnull)
restore[handler.name] = prior
try:
# run the test
yield
finally:
# restore the streams
for handler in handlers.values():
handler.setStream(restore[handler.name])
# close the file we opened
devnull.close()

View file

@ -9,7 +9,7 @@ from epplibwrapper.socket import Socket
from epplibwrapper.utility.pool import EPPConnectionPool from epplibwrapper.utility.pool import EPPConnectionPool
from registrar.models.domain import registry from registrar.models.domain import registry
from contextlib import ExitStack from contextlib import ExitStack
from .common import less_console_noise
import logging import logging
try: try:
@ -135,6 +135,7 @@ class TestConnectionPool(TestCase):
stack.enter_context(patch.object(EPPConnectionPool, "kill_all_connections", do_nothing)) stack.enter_context(patch.object(EPPConnectionPool, "kill_all_connections", do_nothing))
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send)) stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive)) stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
with less_console_noise():
# Restart the connection pool # Restart the connection pool
registry.start_connection_pool() registry.start_connection_pool()
# Pool should be running, and be the right size # Pool should be running, and be the right size
@ -152,6 +153,8 @@ class TestConnectionPool(TestCase):
# The number of open pools should match the number of requested ones. # The number of open pools should match the number of requested ones.
# If it is 0, then they failed to open # If it is 0, then they failed to open
self.assertEqual(len(registry._pool.conn), self.pool_options["size"]) self.assertEqual(len(registry._pool.conn), self.pool_options["size"])
# Kill the connection pool
registry.kill_pool()
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success) @patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
def test_pool_restarts_on_send(self): def test_pool_restarts_on_send(self):
@ -198,16 +201,22 @@ class TestConnectionPool(TestCase):
xml = (location).read_bytes() xml = (location).read_bytes()
return xml return xml
def do_nothing(command):
pass
# Mock what happens inside the "with" # Mock what happens inside the "with"
with ExitStack() as stack: with ExitStack() as stack:
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)) stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
stack.enter_context(patch.object(Socket, "connect", self.fake_client)) stack.enter_context(patch.object(Socket, "connect", self.fake_client))
stack.enter_context(patch.object(EPPConnectionPool, "kill_all_connections", do_nothing))
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send)) stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive)) stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
with less_console_noise():
# Start the connection pool
registry.start_connection_pool()
# Kill the connection pool # Kill the connection pool
registry.kill_pool() registry.kill_pool()
self.assertEqual(registry.pool_status.connection_success, False)
self.assertEqual(registry.pool_status.pool_running, False) self.assertEqual(registry.pool_status.pool_running, False)
# An exception should be raised as end user will be informed # An exception should be raised as end user will be informed
@ -227,6 +236,8 @@ class TestConnectionPool(TestCase):
# The number of open pools should match the number of requested ones. # The number of open pools should match the number of requested ones.
# If it is 0, then they failed to open # If it is 0, then they failed to open
self.assertEqual(len(registry._pool.conn), self.pool_options["size"]) self.assertEqual(len(registry._pool.conn), self.pool_options["size"])
# Kill the connection pool
registry.kill_pool()
@patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success) @patch.object(EPPLibWrapper, "_test_registry_connection_success", patch_success)
def test_raises_connection_error(self): def test_raises_connection_error(self):
@ -236,6 +247,9 @@ class TestConnectionPool(TestCase):
with ExitStack() as stack: with ExitStack() as stack:
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)) stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
stack.enter_context(patch.object(Socket, "connect", self.fake_client)) stack.enter_context(patch.object(Socket, "connect", self.fake_client))
with less_console_noise():
# Start the connection pool
registry.start_connection_pool()
# Pool should be running # Pool should be running
self.assertEqual(registry.pool_status.connection_success, True) self.assertEqual(registry.pool_status.connection_success, True)
@ -246,3 +260,4 @@ class TestConnectionPool(TestCase):
expected = "InfoDomain failed to execute due to a connection error." expected = "InfoDomain failed to execute due to a connection error."
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True) result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
self.assertEqual(result, expected) self.assertEqual(result, expected)

View file

@ -85,6 +85,19 @@ class EPPConnectionPool(ConnectionPool):
logger.error(message, exc_info=True) logger.error(message, exc_info=True)
raise PoolError(code=PoolErrorCodes.KEEP_ALIVE_FAILED) from err raise PoolError(code=PoolErrorCodes.KEEP_ALIVE_FAILED) from err
def _keepalive_periodic(self):
delay = float(self.keepalive) / self.size
while 1:
try:
with self.get() as c:
self._keepalive(c)
except PoolError as err:
logger.error(err.message, exc_info=True)
except self.exc_classes:
# Nothing to do, the pool will generate a new connection later
pass
gevent.sleep(delay)
def _create_socket(self, client, login) -> Socket: def _create_socket(self, client, login) -> Socket:
"""Creates and returns a socket instance""" """Creates and returns a socket instance"""
socket = Socket(client, login) socket = Socket(client, login)

View file

@ -12,6 +12,7 @@ from typing import List, Dict
from django.contrib.sessions.middleware import SessionMiddleware from django.contrib.sessions.middleware import SessionMiddleware
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model, login from django.contrib.auth import get_user_model, login
from django.utils.timezone import make_aware
from registrar.models import ( from registrar.models import (
Contact, Contact,
@ -643,7 +644,7 @@ class MockEppLib(TestCase):
self, self,
id, id,
email, email,
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
pw="thisisnotapassword", pw="thisisnotapassword",
): ):
fake = info.InfoContactResultData( fake = info.InfoContactResultData(
@ -681,7 +682,7 @@ class MockEppLib(TestCase):
mockDataInfoDomain = fakedEppObject( mockDataInfoDomain = fakedEppObject(
"fakePw", "fakePw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)], contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)],
hosts=["fake.host.com"], hosts=["fake.host.com"],
statuses=[ statuses=[
@ -692,7 +693,7 @@ class MockEppLib(TestCase):
) )
mockDataExtensionDomain = fakedEppObject( mockDataExtensionDomain = fakedEppObject(
"fakePw", "fakePw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)], contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)],
hosts=["fake.host.com"], hosts=["fake.host.com"],
statuses=[ statuses=[
@ -706,7 +707,7 @@ class MockEppLib(TestCase):
) )
InfoDomainWithContacts = fakedEppObject( InfoDomainWithContacts = fakedEppObject(
"fakepw", "fakepw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[ contacts=[
common.DomainContact( common.DomainContact(
contact="securityContact", contact="securityContact",
@ -731,7 +732,7 @@ class MockEppLib(TestCase):
InfoDomainWithDefaultSecurityContact = fakedEppObject( InfoDomainWithDefaultSecurityContact = fakedEppObject(
"fakepw", "fakepw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[ contacts=[
common.DomainContact( common.DomainContact(
contact="defaultSec", contact="defaultSec",
@ -750,7 +751,7 @@ class MockEppLib(TestCase):
) )
InfoDomainWithVerisignSecurityContact = fakedEppObject( InfoDomainWithVerisignSecurityContact = fakedEppObject(
"fakepw", "fakepw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[ contacts=[
common.DomainContact( common.DomainContact(
contact="defaultVeri", contact="defaultVeri",
@ -766,7 +767,7 @@ class MockEppLib(TestCase):
InfoDomainWithDefaultTechnicalContact = fakedEppObject( InfoDomainWithDefaultTechnicalContact = fakedEppObject(
"fakepw", "fakepw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[ contacts=[
common.DomainContact( common.DomainContact(
contact="defaultTech", contact="defaultTech",
@ -791,14 +792,14 @@ class MockEppLib(TestCase):
infoDomainNoContact = fakedEppObject( infoDomainNoContact = fakedEppObject(
"security", "security",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[], contacts=[],
hosts=["fake.host.com"], hosts=["fake.host.com"],
) )
infoDomainThreeHosts = fakedEppObject( infoDomainThreeHosts = fakedEppObject(
"my-nameserver.gov", "my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[], contacts=[],
hosts=[ hosts=[
"ns1.my-nameserver-1.com", "ns1.my-nameserver-1.com",
@ -809,25 +810,25 @@ class MockEppLib(TestCase):
infoDomainNoHost = fakedEppObject( infoDomainNoHost = fakedEppObject(
"my-nameserver.gov", "my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[], contacts=[],
hosts=[], hosts=[],
) )
infoDomainTwoHosts = fakedEppObject( infoDomainTwoHosts = fakedEppObject(
"my-nameserver.gov", "my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[], contacts=[],
hosts=["ns1.my-nameserver-1.com", "ns1.my-nameserver-2.com"], hosts=["ns1.my-nameserver-1.com", "ns1.my-nameserver-2.com"],
) )
mockDataInfoHosts = fakedEppObject( mockDataInfoHosts = fakedEppObject(
"lastPw", "lastPw",
cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 8, 25, 19, 45, 35)),
addrs=[common.Ip(addr="1.2.3.4"), common.Ip(addr="2.3.4.5")], addrs=[common.Ip(addr="1.2.3.4"), common.Ip(addr="2.3.4.5")],
) )
mockDataHostChange = fakedEppObject("lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35)) mockDataHostChange = fakedEppObject("lastPw", cr_date=make_aware(datetime.datetime(2023, 8, 25, 19, 45, 35)))
addDsData1 = { addDsData1 = {
"keyTag": 1234, "keyTag": 1234,
"alg": 3, "alg": 3,
@ -859,7 +860,7 @@ class MockEppLib(TestCase):
infoDomainHasIP = fakedEppObject( infoDomainHasIP = fakedEppObject(
"nameserverwithip.gov", "nameserverwithip.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[ contacts=[
common.DomainContact( common.DomainContact(
contact="securityContact", contact="securityContact",
@ -884,7 +885,7 @@ class MockEppLib(TestCase):
justNameserver = fakedEppObject( justNameserver = fakedEppObject(
"justnameserver.com", "justnameserver.com",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[ contacts=[
common.DomainContact( common.DomainContact(
contact="securityContact", contact="securityContact",
@ -907,7 +908,7 @@ class MockEppLib(TestCase):
infoDomainCheckHostIPCombo = fakedEppObject( infoDomainCheckHostIPCombo = fakedEppObject(
"nameserversubdomain.gov", "nameserversubdomain.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)),
contacts=[], contacts=[],
hosts=[ hosts=[
"ns1.nameserversubdomain.gov", "ns1.nameserversubdomain.gov",

View file

@ -59,11 +59,11 @@ class TestDomainAdmin(MockEppLib):
""" """
Make sure the short name is displaying in admin on the list page Make sure the short name is displaying in admin on the list page
""" """
with less_console_noise():
self.client.force_login(self.superuser) self.client.force_login(self.superuser)
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
mock_client = MockSESClient() mock_client = MockSESClient()
with boto3_mocking.clients.handler_for("sesv2", mock_client): with boto3_mocking.clients.handler_for("sesv2", mock_client):
with less_console_noise():
application.approve() application.approve()
response = self.client.get("/admin/registrar/domain/") response = self.client.get("/admin/registrar/domain/")
@ -120,12 +120,12 @@ class TestDomainAdmin(MockEppLib):
Then a user-friendly success message is returned for displaying on the web Then a user-friendly success message is returned for displaying on the web
And `state` is et to `DELETED` And `state` is et to `DELETED`
""" """
with less_console_noise():
domain = create_ready_domain() domain = create_ready_domain()
# Put in client hold # Put in client hold
domain.place_client_hold() domain.place_client_hold()
p = "userpass" p = "userpass"
self.client.login(username="staffuser", password=p) self.client.login(username="staffuser", password=p)
# Ensure everything is displaying correctly # Ensure everything is displaying correctly
response = self.client.get( response = self.client.get(
"/admin/registrar/domain/{}/change/".format(domain.pk), "/admin/registrar/domain/{}/change/".format(domain.pk),
@ -134,7 +134,6 @@ class TestDomainAdmin(MockEppLib):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, domain.name) self.assertContains(response, domain.name)
self.assertContains(response, "Remove from registry") self.assertContains(response, "Remove from registry")
# Test the info dialog # Test the info dialog
request = self.factory.post( request = self.factory.post(
"/admin/registrar/domain/{}/change/".format(domain.pk), "/admin/registrar/domain/{}/change/".format(domain.pk),
@ -142,7 +141,6 @@ class TestDomainAdmin(MockEppLib):
follow=True, follow=True,
) )
request.user = self.client request.user = self.client
with patch("django.contrib.messages.add_message") as mock_add_message: with patch("django.contrib.messages.add_message") as mock_add_message:
self.admin.do_delete_domain(request, domain) self.admin.do_delete_domain(request, domain)
mock_add_message.assert_called_once_with( mock_add_message.assert_called_once_with(
@ -152,7 +150,6 @@ class TestDomainAdmin(MockEppLib):
extra_tags="", extra_tags="",
fail_silently=False, fail_silently=False,
) )
self.assertEqual(domain.state, Domain.State.DELETED) self.assertEqual(domain.state, Domain.State.DELETED)
def test_deletion_ready_fsm_failure(self): def test_deletion_ready_fsm_failure(self):
@ -162,10 +159,10 @@ class TestDomainAdmin(MockEppLib):
Then a user-friendly error message is returned for displaying on the web Then a user-friendly error message is returned for displaying on the web
And `state` is not set to `DELETED` And `state` is not set to `DELETED`
""" """
with less_console_noise():
domain = create_ready_domain() domain = create_ready_domain()
p = "userpass" p = "userpass"
self.client.login(username="staffuser", password=p) self.client.login(username="staffuser", password=p)
# Ensure everything is displaying correctly # Ensure everything is displaying correctly
response = self.client.get( response = self.client.get(
"/admin/registrar/domain/{}/change/".format(domain.pk), "/admin/registrar/domain/{}/change/".format(domain.pk),
@ -174,7 +171,6 @@ class TestDomainAdmin(MockEppLib):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, domain.name) self.assertContains(response, domain.name)
self.assertContains(response, "Remove from registry") self.assertContains(response, "Remove from registry")
# Test the error # Test the error
request = self.factory.post( request = self.factory.post(
"/admin/registrar/domain/{}/change/".format(domain.pk), "/admin/registrar/domain/{}/change/".format(domain.pk),
@ -182,7 +178,6 @@ class TestDomainAdmin(MockEppLib):
follow=True, follow=True,
) )
request.user = self.client request.user = self.client
with patch("django.contrib.messages.add_message") as mock_add_message: with patch("django.contrib.messages.add_message") as mock_add_message:
self.admin.do_delete_domain(request, domain) self.admin.do_delete_domain(request, domain)
mock_add_message.assert_called_once_with( mock_add_message.assert_called_once_with(
@ -205,12 +200,12 @@ class TestDomainAdmin(MockEppLib):
Then `commands.DeleteDomain` is sent to the registry Then `commands.DeleteDomain` is sent to the registry
And Domain returns normally without an error dialog And Domain returns normally without an error dialog
""" """
with less_console_noise():
domain = create_ready_domain() domain = create_ready_domain()
# Put in client hold # Put in client hold
domain.place_client_hold() domain.place_client_hold()
p = "userpass" p = "userpass"
self.client.login(username="staffuser", password=p) self.client.login(username="staffuser", password=p)
# Ensure everything is displaying correctly # Ensure everything is displaying correctly
response = self.client.get( response = self.client.get(
"/admin/registrar/domain/{}/change/".format(domain.pk), "/admin/registrar/domain/{}/change/".format(domain.pk),
@ -219,7 +214,6 @@ class TestDomainAdmin(MockEppLib):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertContains(response, domain.name) self.assertContains(response, domain.name)
self.assertContains(response, "Remove from registry") self.assertContains(response, "Remove from registry")
# Test the info dialog # Test the info dialog
request = self.factory.post( request = self.factory.post(
"/admin/registrar/domain/{}/change/".format(domain.pk), "/admin/registrar/domain/{}/change/".format(domain.pk),
@ -227,7 +221,6 @@ class TestDomainAdmin(MockEppLib):
follow=True, follow=True,
) )
request.user = self.client request.user = self.client
# Delete it once # Delete it once
with patch("django.contrib.messages.add_message") as mock_add_message: with patch("django.contrib.messages.add_message") as mock_add_message:
self.admin.do_delete_domain(request, domain) self.admin.do_delete_domain(request, domain)
@ -240,7 +233,6 @@ class TestDomainAdmin(MockEppLib):
) )
self.assertEqual(domain.state, Domain.State.DELETED) self.assertEqual(domain.state, Domain.State.DELETED)
# Try to delete it again # Try to delete it again
# Test the info dialog # Test the info dialog
request = self.factory.post( request = self.factory.post(
@ -249,7 +241,6 @@ class TestDomainAdmin(MockEppLib):
follow=True, follow=True,
) )
request.user = self.client request.user = self.client
with patch("django.contrib.messages.add_message") as mock_add_message: with patch("django.contrib.messages.add_message") as mock_add_message:
self.admin.do_delete_domain(request, domain) self.admin.do_delete_domain(request, domain)
mock_add_message.assert_called_once_with( mock_add_message.assert_called_once_with(
@ -259,7 +250,6 @@ class TestDomainAdmin(MockEppLib):
extra_tags="", extra_tags="",
fail_silently=False, fail_silently=False,
) )
self.assertEqual(domain.state, Domain.State.DELETED) self.assertEqual(domain.state, Domain.State.DELETED)
@skip("Waiting on epp lib to implement") @skip("Waiting on epp lib to implement")
@ -1281,13 +1271,12 @@ class ListHeaderAdminTest(TestCase):
self.superuser = create_superuser() self.superuser = create_superuser()
def test_changelist_view(self): def test_changelist_view(self):
with less_console_noise():
# Have to get creative to get past linter # Have to get creative to get past linter
p = "adminpass" p = "adminpass"
self.client.login(username="superuser", password=p) self.client.login(username="superuser", password=p)
# Mock a user # Mock a user
user = mock_user() user = mock_user()
# Make the request using the Client class # Make the request using the Client class
# which handles CSRF # which handles CSRF
# Follow=True handles the redirect # Follow=True handles the redirect
@ -1300,7 +1289,6 @@ class ListHeaderAdminTest(TestCase):
}, },
follow=True, follow=True,
) )
# Assert that the filters and search_query are added to the extra_context # Assert that the filters and search_query are added to the extra_context
self.assertIn("filters", response.context) self.assertIn("filters", response.context)
self.assertIn("search_query", response.context) self.assertIn("search_query", response.context)
@ -1320,6 +1308,7 @@ class ListHeaderAdminTest(TestCase):
) )
def test_get_filters(self): def test_get_filters(self):
with less_console_noise():
# Create a mock request object # Create a mock request object
request = self.factory.get("/admin/yourmodel/") request = self.factory.get("/admin/yourmodel/")
# Set the GET parameters for testing # Set the GET parameters for testing
@ -1330,7 +1319,6 @@ class ListHeaderAdminTest(TestCase):
} }
# Call the get_filters method # Call the get_filters method
filters = self.admin.get_filters(request) filters = self.admin.get_filters(request)
# Assert the filters extracted from the request GET # Assert the filters extracted from the request GET
self.assertEqual( self.assertEqual(
filters, filters,
@ -1777,9 +1765,8 @@ class ContactAdminTest(TestCase):
def test_change_view_for_joined_contact_five_or_more(self): def test_change_view_for_joined_contact_five_or_more(self):
"""Create a contact, join it to 5 domain requests. The 6th join will be a user. """Create a contact, join it to 5 domain requests. The 6th join will be a user.
Assert that the warning on the contact form lists 5 joins and a '1 more' ellispsis.""" Assert that the warning on the contact form lists 5 joins and a '1 more' ellispsis."""
with less_console_noise():
self.client.force_login(self.superuser) self.client.force_login(self.superuser)
# Create an instance of the model # Create an instance of the model
# join it to 5 domain requests. The 6th join will be a user. # join it to 5 domain requests. The 6th join will be a user.
contact, _ = Contact.objects.get_or_create(user=self.staffuser) contact, _ = Contact.objects.get_or_create(user=self.staffuser)
@ -1788,13 +1775,10 @@ class ContactAdminTest(TestCase):
application3 = completed_application(submitter=contact, name="city3.gov") application3 = completed_application(submitter=contact, name="city3.gov")
application4 = completed_application(submitter=contact, name="city4.gov") application4 = completed_application(submitter=contact, name="city4.gov")
application5 = completed_application(submitter=contact, name="city5.gov") application5 = completed_application(submitter=contact, name="city5.gov")
with patch("django.contrib.messages.warning") as mock_warning: with patch("django.contrib.messages.warning") as mock_warning:
# Use the test client to simulate the request # Use the test client to simulate the request
response = self.client.get(reverse("admin:registrar_contact_change", args=[contact.pk])) response = self.client.get(reverse("admin:registrar_contact_change", args=[contact.pk]))
logger.debug(mock_warning)
logger.info(mock_warning)
# Assert that the error message was called with the correct argument # Assert that the error message was called with the correct argument
# Note: The 6th join will be a user. # Note: The 6th join will be a user.
mock_warning.assert_called_once_with( mock_warning.assert_called_once_with(

View file

@ -1,5 +1,6 @@
import copy import copy
import datetime from datetime import date, datetime, time
from django.utils import timezone
from django.test import TestCase from django.test import TestCase
@ -17,7 +18,7 @@ from django.core.management import call_command
from unittest.mock import patch, call from unittest.mock import patch, call
from epplibwrapper import commands, common from epplibwrapper import commands, common
from .common import MockEppLib from .common import MockEppLib, less_console_noise
class TestPopulateFirstReady(TestCase): class TestPopulateFirstReady(TestCase):
@ -33,7 +34,9 @@ class TestPopulateFirstReady(TestCase):
self.unknown_domain, _ = Domain.objects.get_or_create(name="fakeunknown.gov", state=Domain.State.UNKNOWN) self.unknown_domain, _ = Domain.objects.get_or_create(name="fakeunknown.gov", state=Domain.State.UNKNOWN)
# Set a ready_at date for testing purposes # Set a ready_at date for testing purposes
self.ready_at_date = datetime.date(2022, 12, 31) self.ready_at_date = date(2022, 12, 31)
_ready_at_datetime = datetime.combine(self.ready_at_date, time.min)
self.ready_at_date_tz_aware = timezone.make_aware(_ready_at_datetime, timezone=timezone.utc)
def tearDown(self): def tearDown(self):
"""Deletes all DB objects related to migrations""" """Deletes all DB objects related to migrations"""
@ -49,6 +52,7 @@ class TestPopulateFirstReady(TestCase):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the populate_first_ready command with the specified arguments. execute the populate_first_ready command with the specified arguments.
""" """
with less_console_noise():
with patch( with patch(
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa "registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
return_value=True, return_value=True,
@ -59,19 +63,15 @@ class TestPopulateFirstReady(TestCase):
""" """
Tests that the populate_first_ready works as expected for the state 'ready' Tests that the populate_first_ready works as expected for the state 'ready'
""" """
with less_console_noise():
# Set the created at date # Set the created at date
self.ready_domain.created_at = self.ready_at_date self.ready_domain.created_at = self.ready_at_date_tz_aware
self.ready_domain.save() self.ready_domain.save()
desired_domain = copy.deepcopy(self.ready_domain) desired_domain = copy.deepcopy(self.ready_domain)
desired_domain.first_ready = self.ready_at_date desired_domain.first_ready = self.ready_at_date
# Run the expiration date script # Run the expiration date script
self.run_populate_first_ready() self.run_populate_first_ready()
self.assertEqual(desired_domain, self.ready_domain) self.assertEqual(desired_domain, self.ready_domain)
# Explicitly test the first_ready date # Explicitly test the first_ready date
first_ready = Domain.objects.filter(name="fakeready.gov").get().first_ready first_ready = Domain.objects.filter(name="fakeready.gov").get().first_ready
self.assertEqual(first_ready, self.ready_at_date) self.assertEqual(first_ready, self.ready_at_date)
@ -80,19 +80,15 @@ class TestPopulateFirstReady(TestCase):
""" """
Tests that the populate_first_ready works as expected for the state 'deleted' Tests that the populate_first_ready works as expected for the state 'deleted'
""" """
with less_console_noise():
# Set the created at date # Set the created at date
self.deleted_domain.created_at = self.ready_at_date self.deleted_domain.created_at = self.ready_at_date_tz_aware
self.deleted_domain.save() self.deleted_domain.save()
desired_domain = copy.deepcopy(self.deleted_domain) desired_domain = copy.deepcopy(self.deleted_domain)
desired_domain.first_ready = self.ready_at_date desired_domain.first_ready = self.ready_at_date
# Run the expiration date script # Run the expiration date script
self.run_populate_first_ready() self.run_populate_first_ready()
self.assertEqual(desired_domain, self.deleted_domain) self.assertEqual(desired_domain, self.deleted_domain)
# Explicitly test the first_ready date # Explicitly test the first_ready date
first_ready = Domain.objects.filter(name="fakedeleted.gov").get().first_ready first_ready = Domain.objects.filter(name="fakedeleted.gov").get().first_ready
self.assertEqual(first_ready, self.ready_at_date) self.assertEqual(first_ready, self.ready_at_date)
@ -101,23 +97,18 @@ class TestPopulateFirstReady(TestCase):
""" """
Tests that the populate_first_ready doesn't make changes when a domain's state is 'dns_needed' Tests that the populate_first_ready doesn't make changes when a domain's state is 'dns_needed'
""" """
with less_console_noise():
# Set the created at date # Set the created at date
self.dns_needed_domain.created_at = self.ready_at_date self.dns_needed_domain.created_at = self.ready_at_date_tz_aware
self.dns_needed_domain.save() self.dns_needed_domain.save()
desired_domain = copy.deepcopy(self.dns_needed_domain) desired_domain = copy.deepcopy(self.dns_needed_domain)
desired_domain.first_ready = None desired_domain.first_ready = None
# Run the expiration date script # Run the expiration date script
self.run_populate_first_ready() self.run_populate_first_ready()
current_domain = self.dns_needed_domain current_domain = self.dns_needed_domain
# The object should largely be unaltered (does not test first_ready) # The object should largely be unaltered (does not test first_ready)
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
first_ready = Domain.objects.filter(name="fakedns.gov").get().first_ready first_ready = Domain.objects.filter(name="fakedns.gov").get().first_ready
# Explicitly test the first_ready date # Explicitly test the first_ready date
self.assertNotEqual(first_ready, self.ready_at_date) self.assertNotEqual(first_ready, self.ready_at_date)
self.assertEqual(first_ready, None) self.assertEqual(first_ready, None)
@ -126,18 +117,15 @@ class TestPopulateFirstReady(TestCase):
""" """
Tests that the populate_first_ready works as expected for the state 'on_hold' Tests that the populate_first_ready works as expected for the state 'on_hold'
""" """
self.hold_domain.created_at = self.ready_at_date with less_console_noise():
self.hold_domain.created_at = self.ready_at_date_tz_aware
self.hold_domain.save() self.hold_domain.save()
desired_domain = copy.deepcopy(self.hold_domain) desired_domain = copy.deepcopy(self.hold_domain)
desired_domain.first_ready = self.ready_at_date desired_domain.first_ready = self.ready_at_date
# Run the update first ready_at script # Run the update first ready_at script
self.run_populate_first_ready() self.run_populate_first_ready()
current_domain = self.hold_domain current_domain = self.hold_domain
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
# Explicitly test the first_ready date # Explicitly test the first_ready date
first_ready = Domain.objects.filter(name="fakehold.gov").get().first_ready first_ready = Domain.objects.filter(name="fakehold.gov").get().first_ready
self.assertEqual(first_ready, self.ready_at_date) self.assertEqual(first_ready, self.ready_at_date)
@ -146,21 +134,17 @@ class TestPopulateFirstReady(TestCase):
""" """
Tests that the populate_first_ready works as expected for the state 'unknown' Tests that the populate_first_ready works as expected for the state 'unknown'
""" """
with less_console_noise():
# Set the created at date # Set the created at date
self.unknown_domain.created_at = self.ready_at_date self.unknown_domain.created_at = self.ready_at_date_tz_aware
self.unknown_domain.save() self.unknown_domain.save()
desired_domain = copy.deepcopy(self.unknown_domain) desired_domain = copy.deepcopy(self.unknown_domain)
desired_domain.first_ready = None desired_domain.first_ready = None
# Run the expiration date script # Run the expiration date script
self.run_populate_first_ready() self.run_populate_first_ready()
current_domain = self.unknown_domain current_domain = self.unknown_domain
# The object should largely be unaltered (does not test first_ready) # The object should largely be unaltered (does not test first_ready)
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
# Explicitly test the first_ready date # Explicitly test the first_ready date
first_ready = Domain.objects.filter(name="fakeunknown.gov").get().first_ready first_ready = Domain.objects.filter(name="fakeunknown.gov").get().first_ready
self.assertNotEqual(first_ready, self.ready_at_date) self.assertNotEqual(first_ready, self.ready_at_date)
@ -185,6 +169,7 @@ class TestPatchAgencyInfo(TestCase):
@patch("registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", return_value=True) @patch("registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", return_value=True)
def call_patch_federal_agency_info(self, mock_prompt): def call_patch_federal_agency_info(self, mock_prompt):
"""Calls the patch_federal_agency_info command and mimics a keypress""" """Calls the patch_federal_agency_info command and mimics a keypress"""
with less_console_noise():
call_command("patch_federal_agency_info", "registrar/tests/data/fake_current_full.csv", debug=True) call_command("patch_federal_agency_info", "registrar/tests/data/fake_current_full.csv", debug=True)
def test_patch_agency_info(self): def test_patch_agency_info(self):
@ -194,15 +179,12 @@ class TestPatchAgencyInfo(TestCase):
of a `DomainInformation` object when the corresponding of a `DomainInformation` object when the corresponding
`TransitionDomain` object has a valid `federal_agency`. `TransitionDomain` object has a valid `federal_agency`.
""" """
with less_console_noise():
# Ensure that the federal_agency is None # Ensure that the federal_agency is None
self.assertEqual(self.domain_info.federal_agency, None) self.assertEqual(self.domain_info.federal_agency, None)
self.call_patch_federal_agency_info() self.call_patch_federal_agency_info()
# Reload the domain_info object from the database # Reload the domain_info object from the database
self.domain_info.refresh_from_db() self.domain_info.refresh_from_db()
# Check that the federal_agency field was updated # Check that the federal_agency field was updated
self.assertEqual(self.domain_info.federal_agency, "test agency") self.assertEqual(self.domain_info.federal_agency, "test agency")
@ -213,19 +195,16 @@ class TestPatchAgencyInfo(TestCase):
of a `DomainInformation` object when the corresponding of a `DomainInformation` object when the corresponding
`TransitionDomain` object does not exist. `TransitionDomain` object does not exist.
""" """
with less_console_noise():
# Set federal_agency to None to simulate a skip # Set federal_agency to None to simulate a skip
self.transition_domain.federal_agency = None self.transition_domain.federal_agency = None
self.transition_domain.save() self.transition_domain.save()
with self.assertLogs("registrar.management.commands.patch_federal_agency_info", level="WARNING") as context: with self.assertLogs("registrar.management.commands.patch_federal_agency_info", level="WARNING") as context:
self.call_patch_federal_agency_info() self.call_patch_federal_agency_info()
# Check that the correct log message was output # Check that the correct log message was output
self.assertIn("SOME AGENCY DATA WAS NONE", context.output[0]) self.assertIn("SOME AGENCY DATA WAS NONE", context.output[0])
# Reload the domain_info object from the database # Reload the domain_info object from the database
self.domain_info.refresh_from_db() self.domain_info.refresh_from_db()
# Check that the federal_agency field was not updated # Check that the federal_agency field was not updated
self.assertIsNone(self.domain_info.federal_agency) self.assertIsNone(self.domain_info.federal_agency)
@ -235,23 +214,19 @@ class TestPatchAgencyInfo(TestCase):
updates the DomainInformation object, because a record exists in the updates the DomainInformation object, because a record exists in the
provided current-full.csv file. provided current-full.csv file.
""" """
with less_console_noise():
# Set federal_agency to None to simulate a skip # Set federal_agency to None to simulate a skip
self.transition_domain.federal_agency = None self.transition_domain.federal_agency = None
self.transition_domain.save() self.transition_domain.save()
# Change the domain name to something parsable in the .csv # Change the domain name to something parsable in the .csv
self.domain.name = "cdomain1.gov" self.domain.name = "cdomain1.gov"
self.domain.save() self.domain.save()
with self.assertLogs("registrar.management.commands.patch_federal_agency_info", level="WARNING") as context: with self.assertLogs("registrar.management.commands.patch_federal_agency_info", level="WARNING") as context:
self.call_patch_federal_agency_info() self.call_patch_federal_agency_info()
# Check that the correct log message was output # Check that the correct log message was output
self.assertIn("SOME AGENCY DATA WAS NONE", context.output[0]) self.assertIn("SOME AGENCY DATA WAS NONE", context.output[0])
# Reload the domain_info object from the database # Reload the domain_info object from the database
self.domain_info.refresh_from_db() self.domain_info.refresh_from_db()
# Check that the federal_agency field was not updated # Check that the federal_agency field was not updated
self.assertEqual(self.domain_info.federal_agency, "World War I Centennial Commission") self.assertEqual(self.domain_info.federal_agency, "World War I Centennial Commission")
@ -261,18 +236,15 @@ class TestPatchAgencyInfo(TestCase):
does not update the `federal_agency` field does not update the `federal_agency` field
of a `DomainInformation` object of a `DomainInformation` object
""" """
with less_console_noise():
self.domain_info.federal_agency = "unchanged" self.domain_info.federal_agency = "unchanged"
self.domain_info.save() self.domain_info.save()
with self.assertLogs("registrar.management.commands.patch_federal_agency_info", level="INFO") as context: with self.assertLogs("registrar.management.commands.patch_federal_agency_info", level="INFO") as context:
self.call_patch_federal_agency_info() self.call_patch_federal_agency_info()
# Check that the correct log message was output # Check that the correct log message was output
self.assertIn("FINISHED", context.output[1]) self.assertIn("FINISHED", context.output[1])
# Reload the domain_info object from the database # Reload the domain_info object from the database
self.domain_info.refresh_from_db() self.domain_info.refresh_from_db()
# Check that the federal_agency field was not updated # Check that the federal_agency field was not updated
self.assertEqual(self.domain_info.federal_agency, "unchanged") self.assertEqual(self.domain_info.federal_agency, "unchanged")
@ -283,39 +255,39 @@ class TestExtendExpirationDates(MockEppLib):
super().setUp() super().setUp()
# Create a valid domain that is updatable # Create a valid domain that is updatable
Domain.objects.get_or_create( Domain.objects.get_or_create(
name="waterbutpurple.gov", state=Domain.State.READY, expiration_date=datetime.date(2023, 11, 15) name="waterbutpurple.gov", state=Domain.State.READY, expiration_date=date(2023, 11, 15)
) )
TransitionDomain.objects.get_or_create( TransitionDomain.objects.get_or_create(
username="testytester@mail.com", username="testytester@mail.com",
domain_name="waterbutpurple.gov", domain_name="waterbutpurple.gov",
epp_expiration_date=datetime.date(2023, 11, 15), epp_expiration_date=date(2023, 11, 15),
) )
# Create a domain with an invalid expiration date # Create a domain with an invalid expiration date
Domain.objects.get_or_create( Domain.objects.get_or_create(
name="fake.gov", state=Domain.State.READY, expiration_date=datetime.date(2022, 5, 25) name="fake.gov", state=Domain.State.READY, expiration_date=date(2022, 5, 25)
) )
TransitionDomain.objects.get_or_create( TransitionDomain.objects.get_or_create(
username="themoonisactuallycheese@mail.com", username="themoonisactuallycheese@mail.com",
domain_name="fake.gov", domain_name="fake.gov",
epp_expiration_date=datetime.date(2022, 5, 25), epp_expiration_date=date(2022, 5, 25),
) )
# Create a domain with an invalid state # Create a domain with an invalid state
Domain.objects.get_or_create( Domain.objects.get_or_create(
name="fakeneeded.gov", state=Domain.State.DNS_NEEDED, expiration_date=datetime.date(2023, 11, 15) name="fakeneeded.gov", state=Domain.State.DNS_NEEDED, expiration_date=date(2023, 11, 15)
) )
TransitionDomain.objects.get_or_create( TransitionDomain.objects.get_or_create(
username="fakeneeded@mail.com", username="fakeneeded@mail.com",
domain_name="fakeneeded.gov", domain_name="fakeneeded.gov",
epp_expiration_date=datetime.date(2023, 11, 15), epp_expiration_date=date(2023, 11, 15),
) )
# Create a domain with a date greater than the maximum # Create a domain with a date greater than the maximum
Domain.objects.get_or_create( Domain.objects.get_or_create(
name="fakemaximum.gov", state=Domain.State.READY, expiration_date=datetime.date(2024, 12, 31) name="fakemaximum.gov", state=Domain.State.READY, expiration_date=date(2024, 12, 31)
) )
TransitionDomain.objects.get_or_create( TransitionDomain.objects.get_or_create(
username="fakemaximum@mail.com", username="fakemaximum@mail.com",
domain_name="fakemaximum.gov", domain_name="fakemaximum.gov",
epp_expiration_date=datetime.date(2024, 12, 31), epp_expiration_date=date(2024, 12, 31),
) )
def tearDown(self): def tearDown(self):
@ -338,6 +310,7 @@ class TestExtendExpirationDates(MockEppLib):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the extend_expiration_dates command with the specified arguments. execute the extend_expiration_dates command with the specified arguments.
""" """
with less_console_noise():
with patch( with patch(
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa "registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
return_value=True, return_value=True,
@ -348,44 +321,41 @@ class TestExtendExpirationDates(MockEppLib):
""" """
Tests that the extend_expiration_dates method extends dates as expected Tests that the extend_expiration_dates method extends dates as expected
""" """
with less_console_noise():
desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get() desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
desired_domain.expiration_date = datetime.date(2024, 11, 15) desired_domain.expiration_date = date(2024, 11, 15)
# Run the expiration date script # Run the expiration date script
self.run_extend_expiration_dates() self.run_extend_expiration_dates()
current_domain = Domain.objects.filter(name="waterbutpurple.gov").get() current_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
# Explicitly test the expiration date # Explicitly test the expiration date
self.assertEqual(current_domain.expiration_date, datetime.date(2024, 11, 15)) self.assertEqual(current_domain.expiration_date, date(2024, 11, 15))
def test_extends_expiration_date_skips_non_current(self): def test_extends_expiration_date_skips_non_current(self):
""" """
Tests that the extend_expiration_dates method correctly skips domains Tests that the extend_expiration_dates method correctly skips domains
with an expiration date less than a certain threshold. with an expiration date less than a certain threshold.
""" """
with less_console_noise():
desired_domain = Domain.objects.filter(name="fake.gov").get() desired_domain = Domain.objects.filter(name="fake.gov").get()
desired_domain.expiration_date = datetime.date(2022, 5, 25) desired_domain.expiration_date = date(2022, 5, 25)
# Run the expiration date script # Run the expiration date script
self.run_extend_expiration_dates() self.run_extend_expiration_dates()
current_domain = Domain.objects.filter(name="fake.gov").get() current_domain = Domain.objects.filter(name="fake.gov").get()
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
# Explicitly test the expiration date. The extend_expiration_dates script # Explicitly test the expiration date. The extend_expiration_dates script
# will skip all dates less than date(2023, 11, 15), meaning that this domain # will skip all dates less than date(2023, 11, 15), meaning that this domain
# should not be affected by the change. # should not be affected by the change.
self.assertEqual(current_domain.expiration_date, datetime.date(2022, 5, 25)) self.assertEqual(current_domain.expiration_date, date(2022, 5, 25))
def test_extends_expiration_date_skips_maximum_date(self): def test_extends_expiration_date_skips_maximum_date(self):
""" """
Tests that the extend_expiration_dates method correctly skips domains Tests that the extend_expiration_dates method correctly skips domains
with an expiration date more than a certain threshold. with an expiration date more than a certain threshold.
""" """
with less_console_noise():
desired_domain = Domain.objects.filter(name="fakemaximum.gov").get() desired_domain = Domain.objects.filter(name="fakemaximum.gov").get()
desired_domain.expiration_date = datetime.date(2024, 12, 31) desired_domain.expiration_date = date(2024, 12, 31)
# Run the expiration date script # Run the expiration date script
self.run_extend_expiration_dates() self.run_extend_expiration_dates()
@ -396,14 +366,15 @@ class TestExtendExpirationDates(MockEppLib):
# Explicitly test the expiration date. The extend_expiration_dates script # Explicitly test the expiration date. The extend_expiration_dates script
# will skip all dates less than date(2023, 11, 15), meaning that this domain # will skip all dates less than date(2023, 11, 15), meaning that this domain
# should not be affected by the change. # should not be affected by the change.
self.assertEqual(current_domain.expiration_date, datetime.date(2024, 12, 31)) self.assertEqual(current_domain.expiration_date, date(2024, 12, 31))
def test_extends_expiration_date_skips_non_ready(self): def test_extends_expiration_date_skips_non_ready(self):
""" """
Tests that the extend_expiration_dates method correctly skips domains not in the state "ready" Tests that the extend_expiration_dates method correctly skips domains not in the state "ready"
""" """
with less_console_noise():
desired_domain = Domain.objects.filter(name="fakeneeded.gov").get() desired_domain = Domain.objects.filter(name="fakeneeded.gov").get()
desired_domain.expiration_date = datetime.date(2023, 11, 15) desired_domain.expiration_date = date(2023, 11, 15)
# Run the expiration date script # Run the expiration date script
self.run_extend_expiration_dates() self.run_extend_expiration_dates()
@ -414,7 +385,7 @@ class TestExtendExpirationDates(MockEppLib):
# Explicitly test the expiration date. The extend_expiration_dates script # Explicitly test the expiration date. The extend_expiration_dates script
# will skip all dates less than date(2023, 11, 15), meaning that this domain # will skip all dates less than date(2023, 11, 15), meaning that this domain
# should not be affected by the change. # should not be affected by the change.
self.assertEqual(current_domain.expiration_date, datetime.date(2023, 11, 15)) self.assertEqual(current_domain.expiration_date, date(2023, 11, 15))
def test_extends_expiration_date_idempotent(self): def test_extends_expiration_date_idempotent(self):
""" """
@ -423,26 +394,21 @@ class TestExtendExpirationDates(MockEppLib):
Verifies that running the method multiple times does not change the expiration date Verifies that running the method multiple times does not change the expiration date
of a domain beyond the initial extension. of a domain beyond the initial extension.
""" """
with less_console_noise():
desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get() desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
desired_domain.expiration_date = datetime.date(2024, 11, 15) desired_domain.expiration_date = date(2024, 11, 15)
# Run the expiration date script # Run the expiration date script
self.run_extend_expiration_dates() self.run_extend_expiration_dates()
current_domain = Domain.objects.filter(name="waterbutpurple.gov").get() current_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
# Explicitly test the expiration date # Explicitly test the expiration date
self.assertEqual(desired_domain.expiration_date, datetime.date(2024, 11, 15)) self.assertEqual(desired_domain.expiration_date, date(2024, 11, 15))
# Run the expiration date script again # Run the expiration date script again
self.run_extend_expiration_dates() self.run_extend_expiration_dates()
# The old domain shouldn't have changed # The old domain shouldn't have changed
self.assertEqual(desired_domain, current_domain) self.assertEqual(desired_domain, current_domain)
# Explicitly test the expiration date - should be the same # Explicitly test the expiration date - should be the same
self.assertEqual(desired_domain.expiration_date, datetime.date(2024, 11, 15)) self.assertEqual(desired_domain.expiration_date, date(2024, 11, 15))
class TestDiscloseEmails(MockEppLib): class TestDiscloseEmails(MockEppLib):
@ -461,6 +427,7 @@ class TestDiscloseEmails(MockEppLib):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the disclose_security_emails command. execute the disclose_security_emails command.
""" """
with less_console_noise():
with patch( with patch(
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa "registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
return_value=True, return_value=True,
@ -472,6 +439,7 @@ class TestDiscloseEmails(MockEppLib):
Tests that command disclose_security_emails runs successfully with Tests that command disclose_security_emails runs successfully with
appropriate EPP calll to UpdateContact. appropriate EPP calll to UpdateContact.
""" """
with less_console_noise():
domain, _ = Domain.objects.get_or_create(name="testdisclose.gov", state=Domain.State.READY) domain, _ = Domain.objects.get_or_create(name="testdisclose.gov", state=Domain.State.READY)
expectedSecContact = PublicContact.get_default_security() expectedSecContact = PublicContact.get_default_security()
expectedSecContact.domain = domain expectedSecContact.domain = domain

View file

@ -60,23 +60,27 @@ class TestDomainApplication(TestCase):
def assertNotRaises(self, exception_type): def assertNotRaises(self, exception_type):
"""Helper method for testing allowed transitions.""" """Helper method for testing allowed transitions."""
with less_console_noise():
return self.assertRaises(Exception, None, exception_type) return self.assertRaises(Exception, None, exception_type)
def test_empty_create_fails(self): def test_empty_create_fails(self):
"""Can't create a completely empty domain application. """Can't create a completely empty domain application.
NOTE: something about theexception this test raises messes up with the NOTE: something about theexception this test raises messes up with the
atomic block in a custom tearDown method for the parent test class.""" atomic block in a custom tearDown method for the parent test class."""
with less_console_noise():
with self.assertRaisesRegex(IntegrityError, "creator"): with self.assertRaisesRegex(IntegrityError, "creator"):
DomainApplication.objects.create() DomainApplication.objects.create()
def test_minimal_create(self): def test_minimal_create(self):
"""Can create with just a creator.""" """Can create with just a creator."""
with less_console_noise():
user, _ = User.objects.get_or_create(username="testy") user, _ = User.objects.get_or_create(username="testy")
application = DomainApplication.objects.create(creator=user) application = DomainApplication.objects.create(creator=user)
self.assertEqual(application.status, DomainApplication.ApplicationStatus.STARTED) self.assertEqual(application.status, DomainApplication.ApplicationStatus.STARTED)
def test_full_create(self): def test_full_create(self):
"""Can create with all fields.""" """Can create with all fields."""
with less_console_noise():
user, _ = User.objects.get_or_create(username="testy") user, _ = User.objects.get_or_create(username="testy")
contact = Contact.objects.create() contact = Contact.objects.create()
com_website, _ = Website.objects.get_or_create(website="igorville.com") com_website, _ = Website.objects.get_or_create(website="igorville.com")
@ -107,6 +111,7 @@ class TestDomainApplication(TestCase):
def test_domain_info(self): def test_domain_info(self):
"""Can create domain info with all fields.""" """Can create domain info with all fields."""
with less_console_noise():
user, _ = User.objects.get_or_create(username="testy") user, _ = User.objects.get_or_create(username="testy")
contact = Contact.objects.create() contact = Contact.objects.create()
domain, _ = Domain.objects.get_or_create(name="igorville.gov") domain, _ = Domain.objects.get_or_create(name="igorville.gov")
@ -133,6 +138,7 @@ class TestDomainApplication(TestCase):
self.assertEqual(information.id, domain.domain_info.id) self.assertEqual(information.id, domain.domain_info.id)
def test_status_fsm_submit_fail(self): def test_status_fsm_submit_fail(self):
with less_console_noise():
user, _ = User.objects.get_or_create(username="testy") user, _ = User.objects.get_or_create(username="testy")
application = DomainApplication.objects.create(creator=user) application = DomainApplication.objects.create(creator=user)
@ -143,6 +149,7 @@ class TestDomainApplication(TestCase):
application.submit() application.submit()
def test_status_fsm_submit_succeed(self): def test_status_fsm_submit_succeed(self):
with less_console_noise():
user, _ = User.objects.get_or_create(username="testy") user, _ = User.objects.get_or_create(username="testy")
site = DraftDomain.objects.create(name="igorville.gov") site = DraftDomain.objects.create(name="igorville.gov")
application = DomainApplication.objects.create(creator=user, requested_domain=site) application = DomainApplication.objects.create(creator=user, requested_domain=site)
@ -156,6 +163,7 @@ class TestDomainApplication(TestCase):
def test_submit_sends_email(self): def test_submit_sends_email(self):
"""Create an application and submit it and see if email was sent.""" """Create an application and submit it and see if email was sent."""
with less_console_noise():
user, _ = User.objects.get_or_create(username="testy") user, _ = User.objects.get_or_create(username="testy")
contact = Contact.objects.create(email="test@test.gov") contact = Contact.objects.create(email="test@test.gov")
domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov") domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
@ -167,7 +175,6 @@ class TestDomainApplication(TestCase):
application.save() application.save()
with boto3_mocking.clients.handler_for("sesv2", self.mock_client): with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
with less_console_noise():
application.submit() application.submit()
# check to see if an email was sent # check to see if an email was sent
@ -268,7 +275,7 @@ class TestDomainApplication(TestCase):
(self.rejected_application, TransitionNotAllowed), (self.rejected_application, TransitionNotAllowed),
(self.ineligible_application, TransitionNotAllowed), (self.ineligible_application, TransitionNotAllowed),
] ]
with less_console_noise():
for application, exception_type in test_cases: for application, exception_type in test_cases:
with self.subTest(application=application, exception_type=exception_type): with self.subTest(application=application, exception_type=exception_type):
try: try:
@ -286,7 +293,7 @@ class TestDomainApplication(TestCase):
(self.action_needed_application, TransitionNotAllowed), (self.action_needed_application, TransitionNotAllowed),
(self.withdrawn_application, TransitionNotAllowed), (self.withdrawn_application, TransitionNotAllowed),
] ]
with less_console_noise():
for application, exception_type in test_cases: for application, exception_type in test_cases:
with self.subTest(application=application, exception_type=exception_type): with self.subTest(application=application, exception_type=exception_type):
with self.assertRaises(exception_type): with self.assertRaises(exception_type):
@ -499,21 +506,25 @@ class TestDomainApplication(TestCase):
def test_has_rationale_returns_true(self): def test_has_rationale_returns_true(self):
"""has_rationale() returns true when an application has no_other_contacts_rationale""" """has_rationale() returns true when an application has no_other_contacts_rationale"""
with less_console_noise():
self.started_application.no_other_contacts_rationale = "You talkin' to me?" self.started_application.no_other_contacts_rationale = "You talkin' to me?"
self.started_application.save() self.started_application.save()
self.assertEquals(self.started_application.has_rationale(), True) self.assertEquals(self.started_application.has_rationale(), True)
def test_has_rationale_returns_false(self): def test_has_rationale_returns_false(self):
"""has_rationale() returns false when an application has no no_other_contacts_rationale""" """has_rationale() returns false when an application has no no_other_contacts_rationale"""
with less_console_noise():
self.assertEquals(self.started_application.has_rationale(), False) self.assertEquals(self.started_application.has_rationale(), False)
def test_has_other_contacts_returns_true(self): def test_has_other_contacts_returns_true(self):
"""has_other_contacts() returns true when an application has other_contacts""" """has_other_contacts() returns true when an application has other_contacts"""
with less_console_noise():
# completed_application has other contacts by default # completed_application has other contacts by default
self.assertEquals(self.started_application.has_other_contacts(), True) self.assertEquals(self.started_application.has_other_contacts(), True)
def test_has_other_contacts_returns_false(self): def test_has_other_contacts_returns_false(self):
"""has_other_contacts() returns false when an application has no other_contacts""" """has_other_contacts() returns false when an application has no other_contacts"""
with less_console_noise():
application = completed_application( application = completed_application(
status=DomainApplication.ApplicationStatus.STARTED, name="no-others.gov", has_other_contacts=False status=DomainApplication.ApplicationStatus.STARTED, name="no-others.gov", has_other_contacts=False
) )

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,7 @@ import boto3_mocking
from registrar.utility.s3_bucket import S3ClientError, S3ClientErrorCodes # type: ignore from registrar.utility.s3_bucket import S3ClientError, S3ClientErrorCodes # type: ignore
from datetime import date, datetime, timedelta from datetime import date, datetime, timedelta
from django.utils import timezone from django.utils import timezone
from .common import less_console_noise
class CsvReportsTest(TestCase): class CsvReportsTest(TestCase):
"""Tests to determine if we are uploading our reports correctly""" """Tests to determine if we are uploading our reports correctly"""
@ -80,6 +80,7 @@ class CsvReportsTest(TestCase):
@boto3_mocking.patching @boto3_mocking.patching
def test_generate_federal_report(self): def test_generate_federal_report(self):
"""Ensures that we correctly generate current-federal.csv""" """Ensures that we correctly generate current-federal.csv"""
with less_console_noise():
mock_client = MagicMock() mock_client = MagicMock()
fake_open = mock_open() fake_open = mock_open()
expected_file_content = [ expected_file_content = [
@ -99,6 +100,7 @@ class CsvReportsTest(TestCase):
@boto3_mocking.patching @boto3_mocking.patching
def test_generate_full_report(self): def test_generate_full_report(self):
"""Ensures that we correctly generate current-full.csv""" """Ensures that we correctly generate current-full.csv"""
with less_console_noise():
mock_client = MagicMock() mock_client = MagicMock()
fake_open = mock_open() fake_open = mock_open()
expected_file_content = [ expected_file_content = [
@ -122,7 +124,7 @@ class CsvReportsTest(TestCase):
def side_effect(Bucket, Key): def side_effect(Bucket, Key):
raise ClientError({"Error": {"Code": "NoSuchKey", "Message": "No such key"}}, "get_object") raise ClientError({"Error": {"Code": "NoSuchKey", "Message": "No such key"}}, "get_object")
with less_console_noise():
mock_client = MagicMock() mock_client = MagicMock()
mock_client.get_object.side_effect = side_effect mock_client.get_object.side_effect = side_effect
@ -143,7 +145,7 @@ class CsvReportsTest(TestCase):
def side_effect(Bucket, Key): def side_effect(Bucket, Key):
raise ClientError({"Error": {"Code": "NoSuchKey", "Message": "No such key"}}, "get_object") raise ClientError({"Error": {"Code": "NoSuchKey", "Message": "No such key"}}, "get_object")
with less_console_noise():
mock_client = MagicMock() mock_client = MagicMock()
mock_client.get_object.side_effect = side_effect mock_client.get_object.side_effect = side_effect
@ -160,6 +162,7 @@ class CsvReportsTest(TestCase):
@boto3_mocking.patching @boto3_mocking.patching
def test_load_federal_report(self): def test_load_federal_report(self):
"""Tests the get_current_federal api endpoint""" """Tests the get_current_federal api endpoint"""
with less_console_noise():
mock_client = MagicMock() mock_client = MagicMock()
mock_client_instance = mock_client.return_value mock_client_instance = mock_client.return_value
@ -192,6 +195,7 @@ class CsvReportsTest(TestCase):
@boto3_mocking.patching @boto3_mocking.patching
def test_load_full_report(self): def test_load_full_report(self):
"""Tests the current-federal api link""" """Tests the current-federal api link"""
with less_console_noise():
mock_client = MagicMock() mock_client = MagicMock()
mock_client_instance = mock_client.return_value mock_client_instance = mock_client.return_value
@ -339,24 +343,19 @@ class ExportDataTest(MockEppLib):
def test_export_domains_to_writer_security_emails(self): def test_export_domains_to_writer_security_emails(self):
"""Test that export_domains_to_writer returns the """Test that export_domains_to_writer returns the
expected security email""" expected security email"""
with less_console_noise():
# Add security email information # Add security email information
self.domain_1.name = "defaultsecurity.gov" self.domain_1.name = "defaultsecurity.gov"
self.domain_1.save() self.domain_1.save()
# Invoke setter # Invoke setter
self.domain_1.security_contact self.domain_1.security_contact
# Invoke setter # Invoke setter
self.domain_2.security_contact self.domain_2.security_contact
# Invoke setter # Invoke setter
self.domain_3.security_contact self.domain_3.security_contact
# Create a CSV file in memory # Create a CSV file in memory
csv_file = StringIO() csv_file = StringIO()
writer = csv.writer(csv_file) writer = csv.writer(csv_file)
# Define columns, sort fields, and filter condition # Define columns, sort fields, and filter condition
columns = [ columns = [
"Domain name", "Domain name",
@ -379,18 +378,14 @@ class ExportDataTest(MockEppLib):
Domain.State.ON_HOLD, Domain.State.ON_HOLD,
], ],
} }
self.maxDiff = None self.maxDiff = None
# Call the export functions # Call the export functions
write_header(writer, columns) write_header(writer, columns)
write_body(writer, columns, sort_fields, filter_condition) write_body(writer, columns, sort_fields, filter_condition)
# Reset the CSV file's position to the beginning # Reset the CSV file's position to the beginning
csv_file.seek(0) csv_file.seek(0)
# Read the content into a variable # Read the content into a variable
csv_content = csv_file.read() csv_content = csv_file.read()
# We expect READY domains, # We expect READY domains,
# sorted alphabetially by domain name # sorted alphabetially by domain name
expected_content = ( expected_content = (
@ -401,18 +396,17 @@ class ExportDataTest(MockEppLib):
"ddomain3.gov,Federal,Armed Forces Retirement Home,123@mail.gov,On hold,2023-05-25\n" "ddomain3.gov,Federal,Armed Forces Retirement Home,123@mail.gov,On hold,2023-05-25\n"
"defaultsecurity.gov,Federal - Executive,World War I Centennial Commission,(blank),Ready" "defaultsecurity.gov,Federal - Executive,World War I Centennial Commission,(blank),Ready"
) )
# Normalize line endings and remove commas, # Normalize line endings and remove commas,
# spaces and leading/trailing whitespace # spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip() csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip() expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
def test_write_body(self): def test_write_body(self):
"""Test that write_body returns the """Test that write_body returns the
existing domain, test that sort by domain name works, existing domain, test that sort by domain name works,
test that filter works""" test that filter works"""
with less_console_noise():
# Create a CSV file in memory # Create a CSV file in memory
csv_file = StringIO() csv_file = StringIO()
writer = csv.writer(csv_file) writer = csv.writer(csv_file)
@ -442,17 +436,13 @@ class ExportDataTest(MockEppLib):
Domain.State.ON_HOLD, Domain.State.ON_HOLD,
], ],
} }
# Call the export functions # Call the export functions
write_header(writer, columns) write_header(writer, columns)
write_body(writer, columns, sort_fields, filter_condition) write_body(writer, columns, sort_fields, filter_condition)
# Reset the CSV file's position to the beginning # Reset the CSV file's position to the beginning
csv_file.seek(0) csv_file.seek(0)
# Read the content into a variable # Read the content into a variable
csv_content = csv_file.read() csv_content = csv_file.read()
# We expect READY domains, # We expect READY domains,
# sorted alphabetially by domain name # sorted alphabetially by domain name
expected_content = ( expected_content = (
@ -464,20 +454,18 @@ class ExportDataTest(MockEppLib):
"cdomain1.gov,Federal - Executive,World War I Centennial Commission,Ready\n" "cdomain1.gov,Federal - Executive,World War I Centennial Commission,Ready\n"
"ddomain3.gov,Federal,Armed Forces Retirement Home,On hold\n" "ddomain3.gov,Federal,Armed Forces Retirement Home,On hold\n"
) )
# Normalize line endings and remove commas, # Normalize line endings and remove commas,
# spaces and leading/trailing whitespace # spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip() csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip() expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
def test_write_body_additional(self): def test_write_body_additional(self):
"""An additional test for filters and multi-column sort""" """An additional test for filters and multi-column sort"""
with less_console_noise():
# Create a CSV file in memory # Create a CSV file in memory
csv_file = StringIO() csv_file = StringIO()
writer = csv.writer(csv_file) writer = csv.writer(csv_file)
# Define columns, sort fields, and filter condition # Define columns, sort fields, and filter condition
columns = [ columns = [
"Domain name", "Domain name",
@ -497,17 +485,13 @@ class ExportDataTest(MockEppLib):
Domain.State.ON_HOLD, Domain.State.ON_HOLD,
], ],
} }
# Call the export functions # Call the export functions
write_header(writer, columns) write_header(writer, columns)
write_body(writer, columns, sort_fields, filter_condition) write_body(writer, columns, sort_fields, filter_condition)
# Reset the CSV file's position to the beginning # Reset the CSV file's position to the beginning
csv_file.seek(0) csv_file.seek(0)
# Read the content into a variable # Read the content into a variable
csv_content = csv_file.read() csv_content = csv_file.read()
# We expect READY domains, # We expect READY domains,
# federal only # federal only
# sorted alphabetially by domain name # sorted alphabetially by domain name
@ -518,12 +502,10 @@ class ExportDataTest(MockEppLib):
"cdomain1.gov,Federal - Executive,World War I Centennial Commission\n" "cdomain1.gov,Federal - Executive,World War I Centennial Commission\n"
"ddomain3.gov,Federal,Armed Forces Retirement Home\n" "ddomain3.gov,Federal,Armed Forces Retirement Home\n"
) )
# Normalize line endings and remove commas, # Normalize line endings and remove commas,
# spaces and leading/trailing whitespace # spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip() csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip() expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
def test_write_body_with_date_filter_pulls_domains_in_range(self): def test_write_body_with_date_filter_pulls_domains_in_range(self):
@ -538,7 +520,7 @@ class ExportDataTest(MockEppLib):
which are hard to mock. which are hard to mock.
TODO: Simplify is created_at is not needed for the report.""" TODO: Simplify is created_at is not needed for the report."""
with less_console_noise():
# Create a CSV file in memory # Create a CSV file in memory
csv_file = StringIO() csv_file = StringIO()
writer = csv.writer(csv_file) writer = csv.writer(csv_file)

View file

@ -20,7 +20,9 @@ from registrar.models.contact import Contact
from .common import MockSESClient, less_console_noise from .common import MockSESClient, less_console_noise
import boto3_mocking # type: ignore import boto3_mocking # type: ignore
import logging
logger = logging.getLogger(__name__)
class TestProcessedMigrations(TestCase): class TestProcessedMigrations(TestCase):
"""This test case class is designed to verify the idempotency of migrations """This test case class is designed to verify the idempotency of migrations
@ -55,6 +57,7 @@ class TestProcessedMigrations(TestCase):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the load_transition_domain command with the specified arguments. execute the load_transition_domain command with the specified arguments.
""" """
with less_console_noise():
# noqa here because splitting this up makes it confusing. # noqa here because splitting this up makes it confusing.
# ES501 # ES501
with patch( with patch(
@ -74,6 +77,7 @@ class TestProcessedMigrations(TestCase):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the load_transition_domain command with the specified arguments. execute the load_transition_domain command with the specified arguments.
""" """
with less_console_noise():
call_command("transfer_transition_domains_to_domains") call_command("transfer_transition_domains_to_domains")
def test_domain_idempotent(self): def test_domain_idempotent(self):
@ -81,6 +85,7 @@ class TestProcessedMigrations(TestCase):
This test ensures that the domain transfer process This test ensures that the domain transfer process
is idempotent on Domain and DomainInformation. is idempotent on Domain and DomainInformation.
""" """
with less_console_noise():
unchanged_domain, _ = Domain.objects.get_or_create( unchanged_domain, _ = Domain.objects.get_or_create(
name="testdomain.gov", name="testdomain.gov",
state=Domain.State.READY, state=Domain.State.READY,
@ -139,6 +144,7 @@ class TestProcessedMigrations(TestCase):
""" """
This test checks if a domain is correctly marked as processed in the transition. This test checks if a domain is correctly marked as processed in the transition.
""" """
with less_console_noise():
old_transition_domain, _ = TransitionDomain.objects.get_or_create(domain_name="testdomain.gov") old_transition_domain, _ = TransitionDomain.objects.get_or_create(domain_name="testdomain.gov")
# Asser that old records default to 'True' # Asser that old records default to 'True'
self.assertTrue(old_transition_domain.processed) self.assertTrue(old_transition_domain.processed)
@ -200,6 +206,7 @@ class TestOrganizationMigration(TestCase):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the load_transition_domain command with the specified arguments. execute the load_transition_domain command with the specified arguments.
""" """
with less_console_noise():
# noqa here because splitting this up makes it confusing. # noqa here because splitting this up makes it confusing.
# ES501 # ES501
with patch( with patch(
@ -219,6 +226,7 @@ class TestOrganizationMigration(TestCase):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the load_transition_domain command with the specified arguments. execute the load_transition_domain command with the specified arguments.
""" """
with less_console_noise():
call_command("transfer_transition_domains_to_domains") call_command("transfer_transition_domains_to_domains")
def run_load_organization_data(self): def run_load_organization_data(self):
@ -232,6 +240,7 @@ class TestOrganizationMigration(TestCase):
The 'call_command' function from Django's management framework is then used to The 'call_command' function from Django's management framework is then used to
execute the load_organization_data command with the specified arguments. execute the load_organization_data command with the specified arguments.
""" """
with less_console_noise():
# noqa here (E501) because splitting this up makes it # noqa here (E501) because splitting this up makes it
# confusing to read. # confusing to read.
with patch( with patch(
@ -256,7 +265,6 @@ class TestOrganizationMigration(TestCase):
"""Does a diff between the transition_domain and the following tables: """Does a diff between the transition_domain and the following tables:
domain, domain_information and the domain_invitation. domain, domain_information and the domain_invitation.
Verifies that the data loaded correctly.""" Verifies that the data loaded correctly."""
missing_domains = [] missing_domains = []
duplicate_domains = [] duplicate_domains = []
missing_domain_informations = [] missing_domain_informations = []
@ -301,7 +309,9 @@ class TestOrganizationMigration(TestCase):
The expected result is a set of TransitionDomain objects with specific attributes. The expected result is a set of TransitionDomain objects with specific attributes.
The test fetches the actual TransitionDomain objects from the database and compares them with the expected objects. The test fetches the actual TransitionDomain objects from the database and compares them with the expected objects.
""" # noqa - E501 (harder to read) """
with less_console_noise():
# noqa - E501 (harder to read)
# == First, parse all existing data == # # == First, parse all existing data == #
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -346,7 +356,9 @@ class TestOrganizationMigration(TestCase):
def test_transition_domain_status_unknown(self): def test_transition_domain_status_unknown(self):
""" """
Test that a domain in unknown status can be loaded Test that a domain in unknown status can be loaded
""" # noqa - E501 (harder to read) """
with less_console_noise():
# noqa - E501 (harder to read)
# == First, parse all existing data == # # == First, parse all existing data == #
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -367,6 +379,7 @@ class TestOrganizationMigration(TestCase):
The test fetches the actual DomainInformation object from the database The test fetches the actual DomainInformation object from the database
and compares it with the expected object. and compares it with the expected object.
""" """
with less_console_noise():
# == First, parse all existing data == # # == First, parse all existing data == #
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -410,6 +423,7 @@ class TestOrganizationMigration(TestCase):
The expected result is that the DomainInformation object retains its pre-existing data The expected result is that the DomainInformation object retains its pre-existing data
after the load_organization_data method is run. after the load_organization_data method is run.
""" """
with less_console_noise():
# == First, parse all existing data == # # == First, parse all existing data == #
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -462,6 +476,7 @@ class TestOrganizationMigration(TestCase):
The expected result is that the counts of objects in the database The expected result is that the counts of objects in the database
match the expected counts, indicating that the data has not been corrupted. match the expected counts, indicating that the data has not been corrupted.
""" """
with less_console_noise():
# First, parse all existing data # First, parse all existing data
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -521,6 +536,7 @@ class TestMigrations(TestCase):
UserDomainRole.objects.all().delete() UserDomainRole.objects.all().delete()
def run_load_domains(self): def run_load_domains(self):
with less_console_noise():
# noqa here because splitting this up makes it confusing. # noqa here because splitting this up makes it confusing.
# ES501 # ES501
with patch( with patch(
@ -534,9 +550,11 @@ class TestMigrations(TestCase):
) )
def run_transfer_domains(self): def run_transfer_domains(self):
with less_console_noise():
call_command("transfer_transition_domains_to_domains") call_command("transfer_transition_domains_to_domains")
def run_master_script(self): def run_master_script(self):
with less_console_noise():
# noqa here (E501) because splitting this up makes it # noqa here (E501) because splitting this up makes it
# confusing to read. # confusing to read.
mock_client = MockSESClient() mock_client = MockSESClient()
@ -553,7 +571,7 @@ class TestMigrations(TestCase):
migrationJSON=self.migration_json_filename, migrationJSON=self.migration_json_filename,
disablePrompts=True, disablePrompts=True,
) )
print(f"here: {mock_client.EMAILS_SENT}") logger.debug(f"here: {mock_client.EMAILS_SENT}")
def compare_tables( def compare_tables(
self, self,
@ -607,7 +625,7 @@ class TestMigrations(TestCase):
total_domain_informations = len(DomainInformation.objects.all()) total_domain_informations = len(DomainInformation.objects.all())
total_domain_invitations = len(DomainInvitation.objects.all()) total_domain_invitations = len(DomainInvitation.objects.all())
print( logger.debug(
f""" f"""
total_missing_domains = {len(missing_domains)} total_missing_domains = {len(missing_domains)}
total_duplicate_domains = {len(duplicate_domains)} total_duplicate_domains = {len(duplicate_domains)}
@ -636,7 +654,7 @@ class TestMigrations(TestCase):
follow best practice of limiting the number of assertions per test. follow best practice of limiting the number of assertions per test.
But for now, this will double-check that the script But for now, this will double-check that the script
works as intended.""" works as intended."""
with less_console_noise():
self.run_master_script() self.run_master_script()
# STEP 2: (analyze the tables just like the # STEP 2: (analyze the tables just like the
@ -664,6 +682,7 @@ class TestMigrations(TestCase):
def test_load_empty_transition_domain(self): def test_load_empty_transition_domain(self):
"""Loads TransitionDomains without additional data""" """Loads TransitionDomains without additional data"""
with less_console_noise():
self.run_load_domains() self.run_load_domains()
# STEP 2: (analyze the tables just like the migration # STEP 2: (analyze the tables just like the migration
@ -689,6 +708,7 @@ class TestMigrations(TestCase):
) )
def test_load_full_domain(self): def test_load_full_domain(self):
with less_console_noise():
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -733,6 +753,7 @@ class TestMigrations(TestCase):
self.assertEqual(testdomain.state, "on hold") self.assertEqual(testdomain.state, "on hold")
def test_load_full_domain_information(self): def test_load_full_domain_information(self):
with less_console_noise():
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -800,6 +821,7 @@ class TestMigrations(TestCase):
self.assertEqual(anomaly.creator, Users.get()) self.assertEqual(anomaly.creator, Users.get())
def test_transfer_transition_domains_to_domains(self): def test_transfer_transition_domains_to_domains(self):
with less_console_noise():
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()
@ -825,6 +847,7 @@ class TestMigrations(TestCase):
) )
def test_logins(self): def test_logins(self):
with less_console_noise():
# TODO: setup manually instead of calling other scripts # TODO: setup manually instead of calling other scripts
self.run_load_domains() self.run_load_domains()
self.run_transfer_domains() self.run_transfer_domains()

View file

@ -159,6 +159,7 @@ class LoggedInTests(TestWithUser):
# Given that we are including a subset of items that can be deleted while excluding the rest, # Given that we are including a subset of items that can be deleted while excluding the rest,
# subTest is appropriate here as otherwise we would need many duplicate tests for the same reason. # subTest is appropriate here as otherwise we would need many duplicate tests for the same reason.
with less_console_noise():
draft_domain = DraftDomain.objects.create(name="igorville.gov") draft_domain = DraftDomain.objects.create(name="igorville.gov")
for status in DomainApplication.ApplicationStatus: for status in DomainApplication.ApplicationStatus:
if status not in [ if status not in [
@ -329,7 +330,6 @@ class LoggedInTests(TestWithUser):
with less_console_noise(): with less_console_noise():
response = self.client.get("/request/", follow=True) response = self.client.get("/request/", follow=True)
print(response.status_code)
self.assertEqual(response.status_code, 403) self.assertEqual(response.status_code, 403)
@ -2548,6 +2548,7 @@ class TestDomainDetail(TestDomainOverview):
It shows as 'DNS needed'""" It shows as 'DNS needed'"""
# At the time of this test's writing, there are 6 UNKNOWN domains inherited # At the time of this test's writing, there are 6 UNKNOWN domains inherited
# from constructors. Let's reset. # from constructors. Let's reset.
with less_console_noise():
Domain.objects.all().delete() Domain.objects.all().delete()
UserDomainRole.objects.all().delete() UserDomainRole.objects.all().delete()
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov") self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
@ -2568,6 +2569,7 @@ class TestDomainDetail(TestDomainOverview):
It shows as 'DNS needed'""" It shows as 'DNS needed'"""
# At the time of this test's writing, there are 6 UNKNOWN domains inherited # At the time of this test's writing, there are 6 UNKNOWN domains inherited
# from constructors. Let's reset. # from constructors. Let's reset.
with less_console_noise():
Domain.objects.all().delete() Domain.objects.all().delete()
UserDomainRole.objects.all().delete() UserDomainRole.objects.all().delete()
@ -2590,16 +2592,17 @@ class TestDomainDetail(TestDomainOverview):
"""We could easily duplicate this test for all domain management """We could easily duplicate this test for all domain management
views, but a single url test should be solid enough since all domain views, but a single url test should be solid enough since all domain
management pages share the same permissions class""" management pages share the same permissions class"""
with less_console_noise():
self.user.status = User.RESTRICTED self.user.status = User.RESTRICTED
self.user.save() self.user.save()
home_page = self.app.get("/") home_page = self.app.get("/")
self.assertContains(home_page, "igorville.gov") self.assertContains(home_page, "igorville.gov")
with less_console_noise():
response = self.client.get(reverse("domain", kwargs={"pk": self.domain.id})) response = self.client.get(reverse("domain", kwargs={"pk": self.domain.id}))
self.assertEqual(response.status_code, 403) self.assertEqual(response.status_code, 403)
def test_domain_detail_allowed_for_on_hold(self): def test_domain_detail_allowed_for_on_hold(self):
"""Test that the domain overview page displays for on hold domain""" """Test that the domain overview page displays for on hold domain"""
with less_console_noise():
home_page = self.app.get("/") home_page = self.app.get("/")
self.assertContains(home_page, "on-hold.gov") self.assertContains(home_page, "on-hold.gov")
@ -2608,6 +2611,7 @@ class TestDomainDetail(TestDomainOverview):
self.assertNotContains(detail_page, "Edit") self.assertNotContains(detail_page, "Edit")
def test_domain_detail_see_just_nameserver(self): def test_domain_detail_see_just_nameserver(self):
with less_console_noise():
home_page = self.app.get("/") home_page = self.app.get("/")
self.assertContains(home_page, "justnameserver.com") self.assertContains(home_page, "justnameserver.com")
@ -2619,6 +2623,7 @@ class TestDomainDetail(TestDomainOverview):
self.assertContains(detail_page, "ns2.justnameserver.com") self.assertContains(detail_page, "ns2.justnameserver.com")
def test_domain_detail_see_nameserver_and_ip(self): def test_domain_detail_see_nameserver_and_ip(self):
with less_console_noise():
home_page = self.app.get("/") home_page = self.app.get("/")
self.assertContains(home_page, "nameserverwithip.gov") self.assertContains(home_page, "nameserverwithip.gov")
@ -2637,6 +2642,7 @@ class TestDomainDetail(TestDomainOverview):
def test_domain_detail_with_no_information_or_application(self): def test_domain_detail_with_no_information_or_application(self):
"""Test that domain management page returns 200 and displays error """Test that domain management page returns 200 and displays error
when no domain information or domain application exist""" when no domain information or domain application exist"""
with less_console_noise():
# have to use staff user for this test # have to use staff user for this test
staff_user = create_user() staff_user = create_user()
# staff_user.save() # staff_user.save()
@ -3430,6 +3436,7 @@ class TestDomainContactInformation(TestDomainOverview):
class TestDomainSecurityEmail(TestDomainOverview): class TestDomainSecurityEmail(TestDomainOverview):
def test_domain_security_email_existing_security_contact(self): def test_domain_security_email_existing_security_contact(self):
"""Can load domain's security email page.""" """Can load domain's security email page."""
with less_console_noise():
self.mockSendPatch = patch("registrar.models.domain.registry.send") self.mockSendPatch = patch("registrar.models.domain.registry.send")
self.mockedSendFunction = self.mockSendPatch.start() self.mockedSendFunction = self.mockSendPatch.start()
self.mockedSendFunction.side_effect = self.mockSend self.mockedSendFunction.side_effect = self.mockSend
@ -3447,6 +3454,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
def test_domain_security_email_no_security_contact(self): def test_domain_security_email_no_security_contact(self):
"""Loads a domain with no defined security email. """Loads a domain with no defined security email.
We should not show the default.""" We should not show the default."""
with less_console_noise():
self.mockSendPatch = patch("registrar.models.domain.registry.send") self.mockSendPatch = patch("registrar.models.domain.registry.send")
self.mockedSendFunction = self.mockSendPatch.start() self.mockedSendFunction = self.mockSendPatch.start()
self.mockedSendFunction.side_effect = self.mockSend self.mockedSendFunction.side_effect = self.mockSend
@ -3460,6 +3468,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
def test_domain_security_email(self): def test_domain_security_email(self):
"""Can load domain's security email page.""" """Can load domain's security email page."""
with less_console_noise():
page = self.client.get(reverse("domain-security-email", kwargs={"pk": self.domain.id})) page = self.client.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
self.assertContains(page, "Security email") self.assertContains(page, "Security email")
@ -3467,6 +3476,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
"""Adding a security email works. """Adding a security email works.
Uses self.app WebTest because we need to interact with forms. Uses self.app WebTest because we need to interact with forms.
""" """
with less_console_noise():
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"pk": self.domain.id})) security_email_page = self.app.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
security_email_page.form["security_email"] = "mayor@igorville.gov" security_email_page.form["security_email"] = "mayor@igorville.gov"
@ -3485,25 +3495,22 @@ class TestDomainSecurityEmail(TestDomainOverview):
success_page = result.follow() success_page = result.follow()
self.assertContains(success_page, "The security email for this domain has been updated") self.assertContains(success_page, "The security email for this domain has been updated")
def test_security_email_form_messages(self): def test_domain_security_email_form_messages(self):
""" """
Test against the success and error messages that are defined in the view Test against the success and error messages that are defined in the view
""" """
with less_console_noise():
p = "adminpass" p = "adminpass"
self.client.login(username="superuser", password=p) self.client.login(username="superuser", password=p)
form_data_registry_error = { form_data_registry_error = {
"security_email": "test@failCreate.gov", "security_email": "test@failCreate.gov",
} }
form_data_contact_error = { form_data_contact_error = {
"security_email": "test@contactError.gov", "security_email": "test@contactError.gov",
} }
form_data_success = { form_data_success = {
"security_email": "test@something.gov", "security_email": "test@something.gov",
} }
test_cases = [ test_cases = [
( (
"RegistryError", "RegistryError",
@ -3522,17 +3529,14 @@ class TestDomainSecurityEmail(TestDomainOverview):
), ),
# Add more test cases with different scenarios here # Add more test cases with different scenarios here
] ]
for test_name, data, expected_message in test_cases: for test_name, data, expected_message in test_cases:
response = self.client.post( response = self.client.post(
reverse("domain-security-email", kwargs={"pk": self.domain.id}), reverse("domain-security-email", kwargs={"pk": self.domain.id}),
data=data, data=data,
follow=True, follow=True,
) )
# Check the response status code, content, or any other relevant assertions # Check the response status code, content, or any other relevant assertions
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# Check if the expected message tag is set # Check if the expected message tag is set
if test_name == "RegistryError" or test_name == "ContactError": if test_name == "RegistryError" or test_name == "ContactError":
message_tag = "error" message_tag = "error"
@ -3541,7 +3545,6 @@ class TestDomainSecurityEmail(TestDomainOverview):
else: else:
# Handle other cases if needed # Handle other cases if needed
message_tag = "info" # Change to the appropriate default message_tag = "info" # Change to the appropriate default
# Check the message tag # Check the message tag
messages = list(response.context["messages"]) messages = list(response.context["messages"])
self.assertEqual(len(messages), 1) self.assertEqual(len(messages), 1)