Skip to content

Commit

Permalink
test: Improve command tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jpmckinney committed Aug 23, 2024
1 parent 97c70d0 commit 8ed580f
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 31 deletions.
8 changes: 7 additions & 1 deletion app/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,16 @@ def sla_overdue_applications() -> None:
):
with rollback_on_error(session):
days_passed = application.days_waiting_for_lender(session)

# Email lenders if the SLA days are dwindling.
if days_passed > application.lender.sla_days * app_settings.progress_to_remind_started_applications:
if "email" not in overdue_lenders[application.lender.id]:
overdue_lenders[application.lender.id]["email"] = application.lender.email_group
overdue_lenders[application.lender.id]["name"] = application.lender.name

overdue_lenders[application.lender.id]["count"] += 1

# Email administrators if the SLA days are exceeded.
if days_passed > application.lender.sla_days:
application.overdued_at = datetime.now(application.created_at.tzinfo)

Expand All @@ -333,7 +336,10 @@ def sla_overdue_applications() -> None:

for lender_id, lender_data in overdue_lenders.items():
message_id = mail.send_overdue_application_email_to_lender(
aws.ses_client, lender_data["name"], lender_data["count"], lender_data["email"]
aws.ses_client,
lender_name=lender_data["name"],
lender_email=lender_data["email"],
amount=lender_data["count"],
)
models.Message.create(
session,
Expand Down
130 changes: 101 additions & 29 deletions tests/commands/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datetime import datetime, timedelta

import pytest
from typer.testing import CliRunner

from app import __main__, models
Expand All @@ -9,31 +10,73 @@
runner = CliRunner()


def test_send_reminders_intro(session, mock_send_templated_email, pending_application):
pending_application.expired_at = datetime.now(pending_application.tz) + timedelta(seconds=1)
@pytest.mark.parametrize(
("seconds", "call_count"),
[
(0, 0),
(1, 1),
(app_settings.reminder_days_before_expiration * 86_400, 1),
(app_settings.reminder_days_before_expiration * 86_400 + 1, 0),
],
)
def test_send_reminders_intro(session, mock_send_templated_email, pending_application, seconds, call_count):
pending_application.expired_at = datetime.now(pending_application.tz) + timedelta(seconds=seconds)
session.commit()

with assert_change(mock_send_templated_email, "call_count", 1):
with assert_change(mock_send_templated_email, "call_count", call_count):
result = runner.invoke(__main__.app, ["send-reminders"])

assert_success(
result, "Sending 1 BORROWER_PENDING_APPLICATION_REMINDER...\nSending 0 BORROWER_PENDING_SUBMIT_REMINDER...\n"
result,
(
f"Sending {call_count} BORROWER_PENDING_APPLICATION_REMINDER...\n"
"Sending 0 BORROWER_PENDING_SUBMIT_REMINDER...\n"
),
)

# If run a second time, reminder is not sent.
with assert_change(mock_send_templated_email, "call_count", 0):
result = runner.invoke(__main__.app, ["send-reminders"])

assert_success(
result, "Sending 0 BORROWER_PENDING_APPLICATION_REMINDER...\nSending 0 BORROWER_PENDING_SUBMIT_REMINDER...\n"
)


def test_send_reminders_submit(session, mock_send_templated_email, accepted_application):
@pytest.mark.parametrize(
("seconds", "call_count"),
[
(0, 0),
(1, 1),
(app_settings.reminder_days_before_lapsed * 86_400, 1),
(app_settings.reminder_days_before_lapsed * 86_400 + 1, 0),
],
)
def test_send_reminders_submit(session, mock_send_templated_email, accepted_application, seconds, call_count):
accepted_application.borrower_accepted_at = (
datetime.now(accepted_application.tz)
- timedelta(days=app_settings.days_to_change_to_lapsed)
+ timedelta(days=app_settings.reminder_days_before_lapsed)
+ timedelta(seconds=seconds)
)
session.commit()

with assert_change(mock_send_templated_email, "call_count", 1):
with assert_change(mock_send_templated_email, "call_count", call_count):
result = runner.invoke(__main__.app, ["send-reminders"])

assert_success(
result, "Sending 0 BORROWER_PENDING_APPLICATION_REMINDER...\nSending 1 BORROWER_PENDING_SUBMIT_REMINDER...\n"
result,
(
"Sending 0 BORROWER_PENDING_APPLICATION_REMINDER...\n"
f"Sending {call_count} BORROWER_PENDING_SUBMIT_REMINDER...\n"
),
)

# If run a second time, reminder is not sent.
with assert_change(mock_send_templated_email, "call_count", 0):
result = runner.invoke(__main__.app, ["send-reminders"])

assert_success(
result, "Sending 0 BORROWER_PENDING_APPLICATION_REMINDER...\nSending 0 BORROWER_PENDING_SUBMIT_REMINDER...\n"
)


Expand All @@ -53,41 +96,51 @@ def test_set_lapsed_applications(session, pending_application):
session.commit()

result = runner.invoke(__main__.app, ["update-applications-to-lapsed"])
session.expire_all()

assert_success(result)
assert pending_application.status == models.ApplicationStatus.LAPSED
assert pending_application.application_lapsed_at is not None


def test_set_lapsed_applications_no_lapsed(pending_application):
def test_set_lapsed_applications_no_lapsed(session, pending_application):
result = runner.invoke(__main__.app, ["update-applications-to-lapsed"])
session.expire_all()

assert_success(result)


def test_send_overdue_reminders(reset_database, session, mock_send_templated_email, started_application):
started_application.lender_started_at = datetime.now(started_application.tz) - timedelta(
days=started_application.lender.sla_days + 1
)
session.commit()

with assert_change(mock_send_templated_email, "call_count", 2): # to admin and lender
result = runner.invoke(__main__.app, ["sla-overdue-applications"])

assert_success(result)


def test_send_overdue_reminders_empty(session, mock_send_templated_email, started_application):
assert pending_application.status == models.ApplicationStatus.PENDING
assert pending_application.application_lapsed_at is None


@pytest.mark.parametrize(
("seconds", "call_count", "overdue"),
[
(4 * 86_400, 0, False),
(5 * 86_400, 1, False),
(7 * 86_400, 1, False),
(8 * 86_400, 2, True),
],
)
def test_send_overdue_reminders(
reset_database, session, mock_send_templated_email, started_application, seconds, call_count, overdue
):
# Lapse all applications already in the database.
session.query(models.Application).filter(models.Application.id != started_application.id).update(
{"status": models.ApplicationStatus.LAPSED}
)

started_application.lender_started_at = datetime.now(started_application.tz)
started_application.lender_started_at = datetime.now(started_application.tz) - timedelta(seconds=seconds)
session.commit()

with assert_change(mock_send_templated_email, "call_count", 0):
with assert_change(mock_send_templated_email, "call_count", call_count):
result = runner.invoke(__main__.app, ["sla-overdue-applications"])
session.expire_all()

assert_success(result)
if overdue:
assert started_application.overdued_at is not None
else:
assert started_application.overdued_at is None


def test_remove_data(session, declined_application):
Expand All @@ -97,14 +150,33 @@ def test_remove_data(session, declined_application):
session.commit()

result = runner.invoke(__main__.app, ["remove-dated-application-data"])
session.expire_all()

assert_success(result)


def test_remove_data_no_dated_application(pending_application):
assert declined_application.award.previous is True
assert declined_application.primary_email == ""
assert declined_application.archived_at is not None
assert declined_application.borrower_documents == []
assert declined_application.borrower.legal_name == ""
assert declined_application.borrower.email == ""
assert declined_application.borrower.address == ""
assert declined_application.borrower.legal_identifier == ""
assert declined_application.borrower.source_data == {}


def test_remove_data_no_dated_application(session, pending_application):
result = runner.invoke(__main__.app, ["remove-dated-application-data"])
session.expire_all()

assert_success(result)
assert pending_application.award.previous is False
assert pending_application.primary_email != ""
assert pending_application.archived_at is None
# documents and legal_name are empty, like in the fixture.
assert pending_application.borrower.email != ""
assert pending_application.borrower.address != ""
assert pending_application.borrower.legal_identifier != ""
assert pending_application.borrower.source_data != {}


def test_update_statistic(engine):
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def borrower(session):
legal_name="", # tests expect this to be in missing_data
email="[email protected]",
address="Direccion: Test Address\nCiudad: Test City\nProvincia: No provisto\nEstado: No provisto",
legal_identifier="",
legal_identifier="Test NIT",
type="Test Organization Type",
sector="",
size=models.BorrowerSize.NOT_INFORMED,
Expand Down

0 comments on commit 8ed580f

Please sign in to comment.