mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-17 21:20:32 -04:00
notify-api-861 show eastern time
This commit is contained in:
@@ -17,6 +17,7 @@ from notifications_utils.formatters import nl2br as utils_nl2br
|
||||
from notifications_utils.recipients import InvalidPhoneError, validate_phone_number
|
||||
from notifications_utils.take import Take
|
||||
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
from app.utils.time import parse_naive_dt
|
||||
|
||||
|
||||
@@ -31,13 +32,14 @@ def convert_to_boolean(value):
|
||||
|
||||
|
||||
def format_datetime(date):
|
||||
return "{} at {} UTC".format(format_date(date), format_time_24h(date))
|
||||
return "{} at {} {}".format(
|
||||
format_date(date), format_time_24h(date), get_user_preferred_timezone()
|
||||
)
|
||||
|
||||
|
||||
def format_datetime_24h(date):
|
||||
return "{} at {} UTC".format(
|
||||
format_date(date),
|
||||
format_time_24h(date),
|
||||
return "{} at {} {}".format(
|
||||
format_date(date), format_time_24h(date), get_user_preferred_timezone()
|
||||
)
|
||||
|
||||
|
||||
@@ -46,39 +48,50 @@ def format_time(date):
|
||||
|
||||
|
||||
def format_datetime_normal(date):
|
||||
return "{} at {} UTC".format(format_date_normal(date), format_time_24h(date))
|
||||
return "{} at {} {}".format(
|
||||
format_date_normal(date), format_time_24h(date), get_user_preferred_timezone()
|
||||
)
|
||||
|
||||
|
||||
def format_datetime_short(date):
|
||||
return "{} at {} UTC".format(format_date_short(date), format_time_24h(date))
|
||||
return "{} at {} {}".format(
|
||||
format_date_short(date), format_time_24h(date), get_user_preferred_timezone()
|
||||
)
|
||||
|
||||
|
||||
def format_datetime_relative(date):
|
||||
return "{} at {} UTC".format(get_human_day(date), format_time_24h(date))
|
||||
return "{} at {} {}".format(
|
||||
get_human_day(date), format_time_24h(date), get_user_preferred_timezone()
|
||||
)
|
||||
|
||||
|
||||
def format_datetime_numeric(date):
|
||||
return "{} {} UTC".format(
|
||||
format_date_numeric(date),
|
||||
format_time_24h(date),
|
||||
return "{} {} {}".format(
|
||||
format_date_numeric(date), format_time_24h(date), get_user_preferred_timezone()
|
||||
)
|
||||
|
||||
|
||||
def format_date_numeric(date):
|
||||
date = parse_naive_dt(date)
|
||||
return date.strftime("%Y-%m-%d")
|
||||
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return date.replace(tzinfo=timezone.utc).astimezone(et).strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
def format_time_24h(date):
|
||||
date = parse_naive_dt(date)
|
||||
return date.strftime("%H:%M")
|
||||
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return date.replace(tzinfo=timezone.utc).astimezone(et).strftime("%H:%M")
|
||||
|
||||
|
||||
def get_human_day(time, date_prefix=""):
|
||||
# Add 1 minute to transform 00:00 into ‘midnight today’ instead of ‘midnight tomorrow’
|
||||
time = parse_naive_dt(time)
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
time = time.replace(tzinfo=timezone.utc).astimezone(et)
|
||||
date = (time - timedelta(minutes=1)).date()
|
||||
now = datetime.now(pytz.utc)
|
||||
now = datetime.now(et)
|
||||
|
||||
if date == (now + timedelta(days=1)).date():
|
||||
return "tomorrow"
|
||||
@@ -100,7 +113,8 @@ def get_human_day(time, date_prefix=""):
|
||||
|
||||
def format_date(date):
|
||||
date = parse_naive_dt(date)
|
||||
return date.strftime("%A %d %B %Y")
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return date.replace(tzinfo=timezone.utc).astimezone(et).strftime("%A %d %B %Y")
|
||||
|
||||
|
||||
def format_date_normal(date):
|
||||
@@ -110,7 +124,8 @@ def format_date_normal(date):
|
||||
|
||||
def format_date_short(date):
|
||||
date = parse_naive_dt(date)
|
||||
return _format_datetime_short(date)
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return _format_datetime_short(date.replace(tzinfo=timezone.utc).astimezone(et))
|
||||
|
||||
|
||||
def format_date_human(date):
|
||||
@@ -118,15 +133,17 @@ def format_date_human(date):
|
||||
|
||||
|
||||
def format_datetime_human(date, date_prefix=""):
|
||||
return "{} at {} UTC".format(
|
||||
return "{} at {} {}".format(
|
||||
get_human_day(date, date_prefix="on"),
|
||||
format_time_24h(date),
|
||||
get_user_preferred_timezone(),
|
||||
)
|
||||
|
||||
|
||||
def format_day_of_week(date):
|
||||
date = parse_naive_dt(date)
|
||||
return date.strftime("%A")
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return date.replace(tzinfo=timezone.utc).astimezone(et).strftime("%A")
|
||||
|
||||
|
||||
def _format_datetime_short(datetime):
|
||||
|
||||
@@ -64,15 +64,18 @@ from app.main.validators import (
|
||||
from app.models.feedback import PROBLEM_TICKET_TYPE, QUESTION_TICKET_TYPE
|
||||
from app.models.organization import Organization
|
||||
from app.utils import branding, merge_jsonlike
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
from app.utils.user_permissions import all_ui_permissions, permission_options
|
||||
|
||||
|
||||
def get_time_value_and_label(future_time):
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return (
|
||||
future_time.astimezone(pytz.utc).replace(tzinfo=None).isoformat(),
|
||||
"{} at {} UTC".format(
|
||||
get_human_day(future_time.astimezone(pytz.utc)),
|
||||
get_human_time(future_time.astimezone(pytz.utc)),
|
||||
future_time.astimezone(et).replace(tzinfo=None).isoformat(),
|
||||
"{} at {} {}".format(
|
||||
get_human_day(future_time.astimezone(et)),
|
||||
get_human_time(future_time.astimezone(et)),
|
||||
get_user_preferred_timezone(),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -85,21 +88,25 @@ def get_human_time(time):
|
||||
|
||||
def get_human_day(time, prefix_today_with="T"):
|
||||
# Add 1 hour to get ‘midnight today’ instead of ‘midnight tomorrow’
|
||||
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
time = (time - timedelta(hours=1)).strftime("%A")
|
||||
if time == datetime.now(pytz.utc).strftime("%A"):
|
||||
if time == datetime.now(et).strftime("%A"):
|
||||
return "{}oday".format(prefix_today_with)
|
||||
if time == (datetime.now(pytz.utc) + timedelta(days=1)).strftime("%A"):
|
||||
if time == (datetime.now(et) + timedelta(days=1)).strftime("%A"):
|
||||
return "Tomorrow"
|
||||
return time
|
||||
|
||||
|
||||
def get_furthest_possible_scheduled_time():
|
||||
# We want local time to find date boundaries
|
||||
return (datetime.now(pytz.utc) + timedelta(days=4)).replace(hour=0)
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return (datetime.now(et) + timedelta(days=4)).replace(hour=0)
|
||||
|
||||
|
||||
def get_next_hours_until(until):
|
||||
now = datetime.now(pytz.utc)
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
now = datetime.now(et)
|
||||
hours = int((until - now).total_seconds() / (60 * 60))
|
||||
return [
|
||||
(now + timedelta(hours=i)).replace(minute=0, second=0, microsecond=0)
|
||||
@@ -108,7 +115,8 @@ def get_next_hours_until(until):
|
||||
|
||||
|
||||
def get_next_days_until(until):
|
||||
now = datetime.now(pytz.utc)
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
now = datetime.now(et)
|
||||
days = int((until - now).total_seconds() / (60 * 60 * 24))
|
||||
return [
|
||||
get_human_day((now + timedelta(days=i)), prefix_today_with="Later t")
|
||||
|
||||
@@ -8,13 +8,15 @@ from flask import render_template
|
||||
|
||||
from app import performance_dashboard_api_client, status_api_client
|
||||
from app.main import main
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
|
||||
|
||||
@main.route("/performance")
|
||||
def performance():
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
stats = performance_dashboard_api_client.get_performance_dashboard_stats(
|
||||
start_date=(datetime.now(pytz.utc) - timedelta(days=7)).date(),
|
||||
end_date=datetime.now(pytz.utc).date(),
|
||||
start_date=(datetime.now(et) - timedelta(days=7)).date(),
|
||||
end_date=datetime.now(et).date(),
|
||||
)
|
||||
stats["organizations_using_notify"] = sorted(
|
||||
[
|
||||
@@ -35,4 +37,5 @@ def performance():
|
||||
stats[
|
||||
"count_of_live_services_and_organizations"
|
||||
] = status_api_client.get_count_of_live_services_and_organizations()
|
||||
|
||||
return render_template("views/performance.html", **stats)
|
||||
|
||||
@@ -47,12 +47,14 @@ class User(JSONModel, UserMixin):
|
||||
"password_changed_at",
|
||||
"permissions",
|
||||
"state",
|
||||
"preferred_timezone",
|
||||
}
|
||||
|
||||
def __init__(self, _dict):
|
||||
super().__init__(_dict)
|
||||
self.permissions = _dict.get("permissions", {})
|
||||
self._platform_admin = _dict["platform_admin"]
|
||||
self.preferred_timezone = "US/Eastern"
|
||||
|
||||
@classmethod
|
||||
def from_id(cls, user_id):
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from datetime import datetime
|
||||
from functools import reduce
|
||||
|
||||
import pytz
|
||||
from dateutil import parser
|
||||
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
|
||||
|
||||
def sum_of_statistics(delivery_statistics):
|
||||
statistics_keys = (
|
||||
@@ -24,6 +27,7 @@ def sum_of_statistics(delivery_statistics):
|
||||
|
||||
|
||||
def add_rates_to(delivery_statistics):
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
return dict(
|
||||
emails_failure_rate=get_formatted_percentage(
|
||||
delivery_statistics["emails_failed"],
|
||||
@@ -33,7 +37,7 @@ def add_rates_to(delivery_statistics):
|
||||
delivery_statistics["sms_failed"], delivery_statistics["sms_requested"]
|
||||
),
|
||||
week_end_datetime=parser.parse(
|
||||
delivery_statistics.get("week_end", str(datetime.utcnow()))
|
||||
delivery_statistics.get("week_end", str(datetime.now(et)))
|
||||
),
|
||||
**delivery_statistics
|
||||
)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import datetime
|
||||
|
||||
import pytz
|
||||
from flask import current_app
|
||||
from notifications_utils.recipients import RecipientCSV
|
||||
|
||||
@@ -59,6 +62,10 @@ def get_errors_for_csv(recipients, template_type):
|
||||
return errors
|
||||
|
||||
|
||||
def get_user_preferred_timezone():
|
||||
return "US/Eastern"
|
||||
|
||||
|
||||
def generate_notifications_csv(**kwargs):
|
||||
from app import notification_api_client
|
||||
from app.s3_client.s3_csv_client import s3download
|
||||
@@ -108,6 +115,10 @@ def generate_notifications_csv(**kwargs):
|
||||
**kwargs
|
||||
)
|
||||
for notification in notifications_resp["notifications"]:
|
||||
preferred_tz_created_at = convert_report_date_to_preferred_timezone(
|
||||
notification["created_at"]
|
||||
)
|
||||
|
||||
current_app.logger.info(f"\n\n{notification}")
|
||||
if kwargs.get("job_id"):
|
||||
values = (
|
||||
@@ -126,7 +137,7 @@ def generate_notifications_csv(**kwargs):
|
||||
notification["carrier"],
|
||||
notification["provider_response"],
|
||||
notification["status"],
|
||||
notification["created_at"],
|
||||
preferred_tz_created_at,
|
||||
]
|
||||
)
|
||||
else:
|
||||
@@ -139,7 +150,7 @@ def generate_notifications_csv(**kwargs):
|
||||
notification["carrier"],
|
||||
notification["provider_response"],
|
||||
notification["status"],
|
||||
notification["created_at"],
|
||||
preferred_tz_created_at,
|
||||
]
|
||||
yield Spreadsheet.from_rows([map(str, values)]).as_csv_data
|
||||
|
||||
@@ -148,3 +159,16 @@ def generate_notifications_csv(**kwargs):
|
||||
else:
|
||||
return
|
||||
raise Exception("Should never reach here")
|
||||
|
||||
|
||||
def convert_report_date_to_preferred_timezone(db_date_str_in_utc):
|
||||
date_arr = db_date_str_in_utc.split(" ")
|
||||
db_date_str_in_utc = f"{date_arr[0]}T{date_arr[1]}+00:00"
|
||||
utc_date_obj = datetime.datetime.fromisoformat(db_date_str_in_utc)
|
||||
|
||||
utc_date_obj = utc_date_obj.astimezone(pytz.utc)
|
||||
preferred_timezone = pytz.timezone(get_user_preferred_timezone())
|
||||
preferred_date_obj = utc_date_obj.astimezone(preferred_timezone)
|
||||
preferred_tz_created_at = preferred_date_obj.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
return f"{preferred_tz_created_at} {get_user_preferred_timezone()}"
|
||||
|
||||
@@ -3,9 +3,12 @@ from datetime import datetime
|
||||
import pytz
|
||||
from dateutil import parser
|
||||
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
|
||||
|
||||
def get_current_financial_year():
|
||||
now = datetime.now(pytz.utc)
|
||||
et = pytz.timezone(get_user_preferred_timezone())
|
||||
now = datetime.now(et)
|
||||
current_month = int(now.strftime("%-m"))
|
||||
current_year = int(now.strftime("%Y"))
|
||||
return current_year if current_month > 9 else current_year - 1
|
||||
|
||||
@@ -10,25 +10,25 @@ def test_form_contains_next_24h(notify_admin):
|
||||
|
||||
# Friday
|
||||
assert choices[0] == ("", "Now")
|
||||
assert choices[1] == ("2016-01-01T12:00:00", "Today at noon UTC")
|
||||
assert choices[13] == ("2016-01-02T00:00:00", "Today at midnight UTC")
|
||||
assert choices[1] == ("2016-01-01T07:00:00", "Today at 7am US/Eastern")
|
||||
assert choices[13] == ("2016-01-01T19:00:00", "Today at 7pm US/Eastern")
|
||||
|
||||
# Saturday
|
||||
assert choices[14] == ("2016-01-02T01:00:00", "Tomorrow at 1am UTC")
|
||||
assert choices[37] == ("2016-01-03T00:00:00", "Tomorrow at midnight UTC")
|
||||
assert choices[14] == ("2016-01-01T20:00:00", "Today at 8pm US/Eastern")
|
||||
assert choices[37] == ("2016-01-02T19:00:00", "Tomorrow at 7pm US/Eastern")
|
||||
|
||||
# Sunday
|
||||
assert choices[38] == ("2016-01-03T01:00:00", "Sunday at 1am UTC")
|
||||
assert choices[38] == ("2016-01-02T20:00:00", "Tomorrow at 8pm US/Eastern")
|
||||
|
||||
# Monday
|
||||
assert choices[62] == ("2016-01-04T01:00:00", "Monday at 1am UTC")
|
||||
assert choices[80] == ("2016-01-04T19:00:00", "Monday at 7pm UTC")
|
||||
assert choices[84] == ("2016-01-04T23:00:00", "Monday at 11pm UTC")
|
||||
assert choices[85] == ("2016-01-05T00:00:00", "Monday at midnight UTC")
|
||||
assert choices[62] == ("2016-01-03T20:00:00", "Sunday at 8pm US/Eastern")
|
||||
assert choices[80] == ("2016-01-04T14:00:00", "Monday at 2pm US/Eastern")
|
||||
assert choices[84] == ("2016-01-04T18:00:00", "Monday at 6pm US/Eastern")
|
||||
assert choices[85] == ("2016-01-04T19:00:00", "Monday at 7pm US/Eastern")
|
||||
|
||||
with pytest.raises(IndexError):
|
||||
assert choices[
|
||||
12 + (3 * 24) + 2 # hours left in the day # 3 days # magic number
|
||||
17 + (3 * 24) + 2 # hours left in the day # 3 days # magic number
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -87,38 +87,38 @@ def test_format_number_in_pounds_as_currency(input_number, formatted_number):
|
||||
("time", "human_readable_datetime"),
|
||||
[
|
||||
# incoming in UTC, outgoing in "human formatted" UTC
|
||||
("2018-03-14 09:00", "14 March at 09:00 UTC"),
|
||||
("2018-03-14 19:00", "14 March at 19:00 UTC"),
|
||||
("2018-03-15 09:00", "15 March at 09:00 UTC"),
|
||||
("2018-03-15 19:00", "15 March at 19:00 UTC"),
|
||||
("2018-03-19 09:00", "19 March at 09:00 UTC"),
|
||||
("2018-03-19 19:00", "19 March at 19:00 UTC"),
|
||||
("2018-03-19 23:59", "19 March at 23:59 UTC"),
|
||||
("2018-03-14 09:00", "14 March at 05:00 US/Eastern"),
|
||||
("2018-03-14 19:00", "14 March at 15:00 US/Eastern"),
|
||||
("2018-03-15 09:00", "15 March at 05:00 US/Eastern"),
|
||||
("2018-03-15 19:00", "15 March at 15:00 US/Eastern"),
|
||||
("2018-03-19 09:00", "19 March at 05:00 US/Eastern"),
|
||||
("2018-03-19 19:00", "19 March at 15:00 US/Eastern"),
|
||||
("2018-03-19 23:59", "19 March at 19:59 US/Eastern"),
|
||||
(
|
||||
"2018-03-20 00:00",
|
||||
"19 March at 00:00 UTC",
|
||||
"2018-03-20 04:00",
|
||||
"19 March at 00:00 US/Eastern",
|
||||
), # we specifically refer to 00:00 as belonging to the day before.
|
||||
("2018-03-20 04:01", "yesterday at 04:01 UTC"),
|
||||
("2018-03-20 09:00", "yesterday at 09:00 UTC"),
|
||||
("2018-03-20 19:00", "yesterday at 19:00 UTC"),
|
||||
("2018-03-20 23:59", "yesterday at 23:59 UTC"),
|
||||
("2018-03-20 04:01", "yesterday at 00:01 US/Eastern"),
|
||||
("2018-03-20 09:00", "yesterday at 05:00 US/Eastern"),
|
||||
("2018-03-20 19:00", "yesterday at 15:00 US/Eastern"),
|
||||
("2018-03-20 23:59", "yesterday at 19:59 US/Eastern"),
|
||||
(
|
||||
"2018-03-21 00:00",
|
||||
"yesterday at 00:00 UTC",
|
||||
"2018-03-21 04:00",
|
||||
"yesterday at 00:00 US/Eastern",
|
||||
), # we specifically refer to 00:00 as belonging to the day before.
|
||||
("2018-03-21 04:01", "today at 04:01 UTC"),
|
||||
("2018-03-21 09:00", "today at 09:00 UTC"),
|
||||
("2018-03-21 12:00", "today at 12:00 UTC"),
|
||||
("2018-03-21 19:00", "today at 19:00 UTC"),
|
||||
("2018-03-21 23:59", "today at 23:59 UTC"),
|
||||
("2018-03-22 00:00", "today at 00:00 UTC"),
|
||||
("2018-03-22 04:01", "tomorrow at 04:01 UTC"),
|
||||
("2018-03-22 09:00", "tomorrow at 09:00 UTC"),
|
||||
("2018-03-22 19:00", "tomorrow at 19:00 UTC"),
|
||||
("2018-03-22 23:59", "tomorrow at 23:59 UTC"),
|
||||
("2018-03-23 04:01", "23 March at 04:01 UTC"),
|
||||
("2018-03-23 09:00", "23 March at 09:00 UTC"),
|
||||
("2018-03-23 19:00", "23 March at 19:00 UTC"),
|
||||
("2018-03-21 04:01", "today at 00:01 US/Eastern"),
|
||||
("2018-03-21 09:00", "today at 05:00 US/Eastern"),
|
||||
("2018-03-21 12:00", "today at 08:00 US/Eastern"),
|
||||
("2018-03-21 19:00", "today at 15:00 US/Eastern"),
|
||||
("2018-03-21 23:59", "today at 19:59 US/Eastern"),
|
||||
("2018-03-22 00:00", "today at 20:00 US/Eastern"),
|
||||
("2018-03-22 04:01", "tomorrow at 00:01 US/Eastern"),
|
||||
("2018-03-22 09:00", "tomorrow at 05:00 US/Eastern"),
|
||||
("2018-03-22 19:00", "tomorrow at 15:00 US/Eastern"),
|
||||
("2018-03-22 23:59", "tomorrow at 19:59 US/Eastern"),
|
||||
("2018-03-23 04:01", "23 March at 00:01 US/Eastern"),
|
||||
("2018-03-23 09:00", "23 March at 05:00 US/Eastern"),
|
||||
("2018-03-23 19:00", "23 March at 15:00 US/Eastern"),
|
||||
],
|
||||
)
|
||||
def test_format_datetime_relative(time, human_readable_datetime):
|
||||
|
||||
@@ -159,7 +159,10 @@ def test_can_show_notifications(
|
||||
|
||||
assert normalize_spaces(
|
||||
first_row.select_one(".table-field-right-aligned .align-with-message-body").text
|
||||
) == ("Delivered 1 January at 06:01 UTC")
|
||||
) in [
|
||||
"Delivered 1 January at 02:01 US/Eastern",
|
||||
"Delivered 1 January at 01:01 US/Eastern",
|
||||
]
|
||||
|
||||
assert page_title in page.h1.text.strip()
|
||||
|
||||
@@ -653,31 +656,36 @@ def test_redacts_templates_that_should_be_redacted(
|
||||
@pytest.mark.parametrize(
|
||||
("message_type", "status", "expected_hint_status", "single_line"),
|
||||
[
|
||||
("email", "created", "Sending since 27 September at 12:30 UTC", True),
|
||||
("email", "sending", "Sending since 27 September at 12:30 UTC", True),
|
||||
("email", "created", "Sending since 27 September at 08:30 US/Eastern", True),
|
||||
("email", "sending", "Sending since 27 September at 08:30 US/Eastern", True),
|
||||
(
|
||||
"email",
|
||||
"temporary-failure",
|
||||
"Inbox not accepting messages right now 27 September at 12:31 UTC",
|
||||
"Inbox not accepting messages right now 27 September at 08:31 US/Eastern",
|
||||
False,
|
||||
),
|
||||
(
|
||||
"email",
|
||||
"permanent-failure",
|
||||
"Email address does not exist 27 September at 12:31 UTC",
|
||||
"Email address does not exist 27 September at 08:31 US/Eastern",
|
||||
False,
|
||||
),
|
||||
("email", "delivered", "Delivered 27 September at 12:31 UTC", True),
|
||||
("sms", "created", "Sending since 27 September at 12:30 UTC", True),
|
||||
("sms", "sending", "Sending since 27 September at 12:30 UTC", True),
|
||||
("email", "delivered", "Delivered 27 September at 08:31 US/Eastern", True),
|
||||
("sms", "created", "Sending since 27 September at 08:30 US/Eastern", True),
|
||||
("sms", "sending", "Sending since 27 September at 08:30 US/Eastern", True),
|
||||
(
|
||||
"sms",
|
||||
"temporary-failure",
|
||||
"Phone not accepting messages right now 27 September at 12:31 UTC",
|
||||
"Phone not accepting messages right now 27 September at 08:31 US/Eastern",
|
||||
False,
|
||||
),
|
||||
("sms", "permanent-failure", "Not delivered 27 September at 12:31 UTC", False),
|
||||
("sms", "delivered", "Delivered 27 September at 12:31 UTC", True),
|
||||
(
|
||||
"sms",
|
||||
"permanent-failure",
|
||||
"Not delivered 27 September at 08:31 US/Eastern",
|
||||
False,
|
||||
),
|
||||
("sms", "delivered", "Delivered 27 September at 08:31 US/Eastern", True),
|
||||
],
|
||||
)
|
||||
def test_sending_status_hint_displays_correctly_on_notifications_page(
|
||||
|
||||
@@ -70,7 +70,7 @@ def test_get_user_phone_number_raises_if_both_api_requests_fail(mocker):
|
||||
(False, "Hello Jo"),
|
||||
],
|
||||
)
|
||||
@freeze_time("2012-01-01 00:00:00")
|
||||
@freeze_time("2012-01-01 05:00:00")
|
||||
def test_view_conversation(
|
||||
client_request,
|
||||
mocker,
|
||||
@@ -113,55 +113,55 @@ def test_view_conversation(
|
||||
[
|
||||
(
|
||||
"message-8",
|
||||
"yesterday at 14:59 UTC",
|
||||
"yesterday at 14:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-7",
|
||||
"yesterday at 14:59 UTC",
|
||||
"yesterday at 14:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-6",
|
||||
"yesterday at 16:59 UTC",
|
||||
"yesterday at 16:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-5",
|
||||
"yesterday at 18:59 UTC",
|
||||
"yesterday at 18:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-4",
|
||||
"yesterday at 20:59 UTC",
|
||||
"yesterday at 20:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-3",
|
||||
"yesterday at 22:59 UTC",
|
||||
"yesterday at 22:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-2",
|
||||
"yesterday at 22:59 UTC",
|
||||
"yesterday at 22:59 US/Eastern",
|
||||
),
|
||||
(
|
||||
"message-1",
|
||||
"yesterday at 23:00 UTC",
|
||||
"yesterday at 23:00 US/Eastern",
|
||||
),
|
||||
(
|
||||
expected_outbound_content,
|
||||
"yesterday at 00:00 UTC",
|
||||
"yesterday at 00:00 US/Eastern",
|
||||
),
|
||||
(
|
||||
expected_outbound_content,
|
||||
"yesterday at 00:00 UTC",
|
||||
"yesterday at 00:00 US/Eastern",
|
||||
),
|
||||
(
|
||||
expected_outbound_content,
|
||||
"yesterday at 00:00 UTC",
|
||||
"yesterday at 00:00 US/Eastern",
|
||||
),
|
||||
(
|
||||
expected_outbound_content,
|
||||
"yesterday at 00:00 UTC",
|
||||
"yesterday at 00:00 US/Eastern",
|
||||
),
|
||||
(
|
||||
expected_outbound_content,
|
||||
"yesterday at 00:00 UTC",
|
||||
"yesterday at 00:00 US/Eastern",
|
||||
),
|
||||
]
|
||||
):
|
||||
|
||||
@@ -379,7 +379,7 @@ def test_view_inbox_updates(
|
||||
mock_get_partials.assert_called_once_with(SERVICE_ONE_ID)
|
||||
|
||||
|
||||
@freeze_time("2016-07-01 12:00")
|
||||
@freeze_time("2016-07-01 16:00")
|
||||
def test_download_inbox(
|
||||
client_request,
|
||||
mock_get_inbound_sms,
|
||||
@@ -394,14 +394,14 @@ def test_download_inbox(
|
||||
)
|
||||
assert response.get_data(as_text=True) == (
|
||||
"Phone number,Message,Received\r\n"
|
||||
"(202) 867-5300,message-1,2016-07-01 11:00 UTC\r\n"
|
||||
"(202) 867-5300,message-2,2016-07-01 10:59 UTC\r\n"
|
||||
"(202) 867-5300,message-3,2016-07-01 10:59 UTC\r\n"
|
||||
"(202) 867-5302,message-4,2016-07-01 08:59 UTC\r\n"
|
||||
"+33 1 12 34 56 78,message-5,2016-07-01 06:59 UTC\r\n"
|
||||
"(202) 555-0104,message-6,2016-07-01 04:59 UTC\r\n"
|
||||
"(202) 555-0104,message-7,2016-07-01 02:59 UTC\r\n"
|
||||
"+682 12345,message-8,2016-07-01 02:59 UTC\r\n"
|
||||
"(202) 867-5300,message-1,2016-07-01 11:00 US/Eastern\r\n"
|
||||
"(202) 867-5300,message-2,2016-07-01 10:59 US/Eastern\r\n"
|
||||
"(202) 867-5300,message-3,2016-07-01 10:59 US/Eastern\r\n"
|
||||
"(202) 867-5302,message-4,2016-07-01 08:59 US/Eastern\r\n"
|
||||
"+33 1 12 34 56 78,message-5,2016-07-01 06:59 US/Eastern\r\n"
|
||||
"(202) 555-0104,message-6,2016-07-01 04:59 US/Eastern\r\n"
|
||||
"(202) 555-0104,message-7,2016-07-01 02:59 US/Eastern\r\n"
|
||||
"+682 12345,message-8,2016-07-01 02:59 US/Eastern\r\n"
|
||||
)
|
||||
|
||||
|
||||
@@ -636,7 +636,7 @@ def test_monthly_has_equal_length_tables(
|
||||
assert page.select_one(".table-field-headings th").get("width") == "33%"
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 1:09:00.061258")
|
||||
@freeze_time("2016-01-01 11:09:00.061258")
|
||||
def test_should_show_upcoming_jobs_on_dashboard(
|
||||
client_request,
|
||||
mock_get_service_templates,
|
||||
@@ -659,7 +659,7 @@ def test_should_show_upcoming_jobs_on_dashboard(
|
||||
assert normalize_spaces(page.select_one("main h2").text) == ("In the next few days")
|
||||
|
||||
assert normalize_spaces(page.select_one("a.banner-dashboard").text) == (
|
||||
"2 files waiting to send " "- sending starts today at 11:09 UTC"
|
||||
"2 files waiting to send " "- sending starts today at 06:09 US/Eastern"
|
||||
)
|
||||
|
||||
assert page.select_one("a.banner-dashboard")["href"] == url_for(
|
||||
|
||||
@@ -11,30 +11,30 @@ from tests.conftest import SERVICE_ONE_ID, normalize_spaces
|
||||
{},
|
||||
[
|
||||
(
|
||||
"12 December",
|
||||
"12 December 2012",
|
||||
(
|
||||
"Test User 18:13 "
|
||||
"Test User 13:13 "
|
||||
"Renamed this service from ‘Before lunch’ to ‘After lunch’ "
|
||||
"Test User 17:12 "
|
||||
"Test User 12:12 "
|
||||
"Renamed this service from ‘Example service’ to ‘Before lunch’"
|
||||
),
|
||||
),
|
||||
(
|
||||
"11 November",
|
||||
("Test User 17:12 " "Revoked the ‘Bad key’ API key"),
|
||||
"11 November 2012",
|
||||
("Test User 12:12 " "Revoked the ‘Bad key’ API key"),
|
||||
),
|
||||
(
|
||||
"11 November 2011",
|
||||
("Test User 16:11 " "Created an API key called ‘Bad key’"),
|
||||
"11 November",
|
||||
("Test User 11:11 " "Created an API key called ‘Bad key’"),
|
||||
),
|
||||
(
|
||||
"10 October 2010",
|
||||
(
|
||||
"Test User 15:10 "
|
||||
"Test User 11:10 "
|
||||
"Created an API key called ‘Good key’ "
|
||||
"Test User 14:09 "
|
||||
"Test User 10:09 "
|
||||
"Created an API key called ‘Key event returned in non-chronological order’ "
|
||||
"Test User 06:01 "
|
||||
"Test User 02:01 "
|
||||
"Created this service and called it ‘Example service’"
|
||||
),
|
||||
),
|
||||
@@ -44,19 +44,19 @@ from tests.conftest import SERVICE_ONE_ID, normalize_spaces
|
||||
{"selected": "api"},
|
||||
[
|
||||
(
|
||||
"11 November",
|
||||
("Test User 17:12 " "Revoked the ‘Bad key’ API key"),
|
||||
"11 November 2012",
|
||||
("Test User 12:12 " "Revoked the ‘Bad key’ API key"),
|
||||
),
|
||||
(
|
||||
"11 November 2011",
|
||||
("Test User 16:11 " "Created an API key called ‘Bad key’"),
|
||||
"11 November",
|
||||
("Test User 11:11 " "Created an API key called ‘Bad key’"),
|
||||
),
|
||||
(
|
||||
"10 October 2010",
|
||||
(
|
||||
"Test User 15:10 "
|
||||
"Test User 11:10 "
|
||||
"Created an API key called ‘Good key’ "
|
||||
"Test User 14:09 "
|
||||
"Test User 10:09 "
|
||||
"Created an API key called ‘Key event returned in non-chronological order’"
|
||||
),
|
||||
),
|
||||
@@ -66,18 +66,18 @@ from tests.conftest import SERVICE_ONE_ID, normalize_spaces
|
||||
{"selected": "service"},
|
||||
[
|
||||
(
|
||||
"12 December",
|
||||
"12 December 2012",
|
||||
(
|
||||
"Test User 18:13 "
|
||||
"Test User 13:13 "
|
||||
"Renamed this service from ‘Before lunch’ to ‘After lunch’ "
|
||||
"Test User 17:12 "
|
||||
"Test User 12:12 "
|
||||
"Renamed this service from ‘Example service’ to ‘Before lunch’"
|
||||
),
|
||||
),
|
||||
(
|
||||
"10 October 2010",
|
||||
(
|
||||
"Test User 06:01 "
|
||||
"Test User 02:01 "
|
||||
"Created this service and called it ‘Example service’"
|
||||
),
|
||||
),
|
||||
|
||||
@@ -90,7 +90,7 @@ def test_should_show_page_for_one_job(
|
||||
|
||||
assert page.h1.text.strip() == "thisisatest.csv"
|
||||
assert " ".join(page.find("tbody").find("tr").text.split()) == (
|
||||
"2021234567 template content Delivered 1 January at 11:10 UTC"
|
||||
"2021234567 template content Delivered 1 January at 06:10 US/Eastern"
|
||||
)
|
||||
assert page.find("div", {"data-key": "notifications"})["data-resource"] == url_for(
|
||||
"main.view_job_updates",
|
||||
@@ -109,7 +109,7 @@ def test_should_show_page_for_one_job(
|
||||
assert page.find("span", {"id": "time-left"}).text == "Data available for 7 days"
|
||||
|
||||
assert normalize_spaces(page.select_one("tbody tr").text) == normalize_spaces(
|
||||
"2021234567 " "template content " "Delivered 1 January at 11:10 UTC"
|
||||
"2021234567 " "template content " "Delivered 1 January at 06:10 US/Eastern"
|
||||
)
|
||||
assert page.select_one("tbody tr a")["href"] == url_for(
|
||||
"main.view_notification",
|
||||
@@ -334,7 +334,7 @@ def test_should_show_old_job(
|
||||
]
|
||||
|
||||
|
||||
@freeze_time("2016-01-01T05:00:00.061258")
|
||||
@freeze_time("2016-01-01T06:00:00.061258")
|
||||
def test_should_show_scheduled_job(
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
@@ -350,7 +350,7 @@ def test_should_show_scheduled_job(
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select("main p")[1].text) == (
|
||||
"Sending Two week reminder tomorrow at 05:00 UTC"
|
||||
"Sending Two week reminder today at 00:00 US/Eastern"
|
||||
)
|
||||
assert page.select("main p a")[0]["href"] == url_for(
|
||||
"main.view_template_version",
|
||||
@@ -423,8 +423,8 @@ def test_should_show_updates_for_one_job_as_json(
|
||||
assert "2021234567" in content["notifications"]
|
||||
assert "Status" in content["notifications"]
|
||||
assert "Delivered" in content["notifications"]
|
||||
assert "05:01" in content["notifications"]
|
||||
assert "Sent by Test User on 1 January at 05:00" in content["status"]
|
||||
assert "00:01" in content["notifications"]
|
||||
assert "Sent by Test User on 1 January at 00:00" in content["status"]
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 05:00:00.000001")
|
||||
@@ -465,8 +465,8 @@ def test_should_show_updates_for_scheduled_job_as_json(
|
||||
assert "2021234567" in content["notifications"]
|
||||
assert "Status" in content["notifications"]
|
||||
assert "Delivered" in content["notifications"]
|
||||
assert "05:01" in content["notifications"]
|
||||
assert "Sent by Test User on 1 June at 20:00" in content["status"]
|
||||
assert "00:01" in content["notifications"]
|
||||
assert "Sent by Test User on 1 June at 16:00" in content["status"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -226,19 +226,23 @@ def test_notification_status_shows_expected_back_link(
|
||||
[
|
||||
(
|
||||
"2012-01-01 06:01",
|
||||
("‘sample template’ was sent by Test User today at 06:01 UTC"),
|
||||
("‘sample template’ was sent by Test User today at 01:01 US/Eastern"),
|
||||
),
|
||||
(
|
||||
"2012-01-02 06:01",
|
||||
("‘sample template’ was sent by Test User yesterday at 06:01 UTC"),
|
||||
("‘sample template’ was sent by Test User yesterday at 01:01 US/Eastern"),
|
||||
),
|
||||
(
|
||||
"2012-01-03 06:01",
|
||||
("‘sample template’ was sent by Test User on 1 January at 06:01 UTC"),
|
||||
(
|
||||
"‘sample template’ was sent by Test User on 1 January at 01:01 US/Eastern"
|
||||
),
|
||||
),
|
||||
(
|
||||
"2013-01-03 06:01",
|
||||
("‘sample template’ was sent by Test User on 1 January 2012 at 06:01 UTC"),
|
||||
(
|
||||
"‘sample template’ was sent by Test User on 1 January 2012 at 01:01 US/Eastern"
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -200,7 +200,7 @@ def test_view_providers_shows_all_providers(
|
||||
assert table_data[1].text.strip() == "20"
|
||||
assert table_data[2].text.strip() == "42"
|
||||
assert table_data[3].text.strip() == "True"
|
||||
assert table_data[4].text.strip() == "16 January at 15:20 UTC"
|
||||
assert table_data[4].text.strip() == "16 January at 10:20 US/Eastern"
|
||||
assert table_data[5].text.strip() == "Test User"
|
||||
|
||||
domestic_sms_second_row = domestic_sms_table.tbody.find_all("tr")[1]
|
||||
|
||||
@@ -472,7 +472,7 @@ def test_caseworker_redirected_to_set_sender_for_one_off(
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2020-01-01 15:00")
|
||||
@freeze_time("2020-01-01 20:00")
|
||||
def test_caseworker_sees_template_page_if_template_is_deleted(
|
||||
client_request,
|
||||
mock_get_deleted_template,
|
||||
@@ -497,7 +497,7 @@ def test_caseworker_sees_template_page_if_template_is_deleted(
|
||||
)
|
||||
assert (
|
||||
page.select("p.hint")[0].text.strip()
|
||||
== "This template was deleted today at 15:00 UTC."
|
||||
== "This template was deleted today at 15:00 US/Eastern."
|
||||
)
|
||||
|
||||
mock_get_deleted_template.assert_called_with(SERVICE_ONE_ID, template_id, None)
|
||||
@@ -1573,7 +1573,7 @@ def test_should_redirect_when_deleting_a_template(
|
||||
mock_delete_service_template.assert_called_with(SERVICE_ONE_ID, TEMPLATE_ONE_ID)
|
||||
|
||||
|
||||
@freeze_time("2016-01-01T15:00")
|
||||
@freeze_time("2016-01-01T20:00")
|
||||
def test_should_show_page_for_a_deleted_template(
|
||||
client_request,
|
||||
mock_get_template_folders,
|
||||
@@ -1606,7 +1606,7 @@ def test_should_show_page_for_a_deleted_template(
|
||||
)
|
||||
assert (
|
||||
page.select("p.hint")[0].text.strip()
|
||||
== "This template was deleted today at 15:00 UTC."
|
||||
== "This template was deleted today at 15:00 US/Eastern."
|
||||
)
|
||||
assert "Delete this template" not in page.select_one("main").text
|
||||
|
||||
|
||||
@@ -51,7 +51,9 @@ def test_get_upload_hub_page(
|
||||
assert len(uploads) == 1
|
||||
|
||||
assert normalize_spaces(uploads[0].text.strip()) == (
|
||||
"some.csv " "Sent 1 January 2016 at 11:09 UTC " "0 pending 8 delivered 2 failed"
|
||||
"some.csv "
|
||||
"Sent 1 January 2016 at 06:09 US/Eastern "
|
||||
"0 pending 8 delivered 2 failed"
|
||||
)
|
||||
assert uploads[0].select_one("a.file-list-filename-large")["href"] == (
|
||||
"/services/{}/jobs/job_id_1".format(SERVICE_ONE_ID)
|
||||
@@ -80,12 +82,12 @@ def test_uploads_page_shows_scheduled_jobs(
|
||||
("File Status"),
|
||||
(
|
||||
"even_later.csv "
|
||||
"Sending 1 January 2016 at 23:09 UTC "
|
||||
"Sending 1 January 2016 at 18:09 US/Eastern "
|
||||
"1 text message waiting to send"
|
||||
),
|
||||
(
|
||||
"send_me_later.csv "
|
||||
"Sending 1 January 2016 at 11:09 UTC "
|
||||
"Sending 1 January 2016 at 06:09 US/Eastern "
|
||||
"1 text message waiting to send"
|
||||
),
|
||||
]
|
||||
|
||||
@@ -4,7 +4,11 @@ from io import StringIO
|
||||
|
||||
import pytest
|
||||
|
||||
from app.utils.csv import generate_notifications_csv, get_errors_for_csv
|
||||
from app.utils.csv import (
|
||||
convert_report_date_to_preferred_timezone,
|
||||
generate_notifications_csv,
|
||||
get_errors_for_csv,
|
||||
)
|
||||
from tests.conftest import fake_uuid
|
||||
|
||||
|
||||
@@ -87,14 +91,14 @@ def get_notifications_csv_mock(
|
||||
None,
|
||||
[
|
||||
"Recipient,Template,Type,Sent by,Job,Carrier,Carrier Response,Status,Time\n",
|
||||
"foo@bar.com,foo,sms,,,ATT Mobility,Did not like it,Delivered,1943-04-19 12:00:00\r\n",
|
||||
"foo@bar.com,foo,sms,,,ATT Mobility,Did not like it,Delivered,1943-04-19 08:00:00 US/Eastern\r\n",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Anne Example",
|
||||
[
|
||||
"Recipient,Template,Type,Sent by,Job,Carrier,Carrier Response,Status,Time\n",
|
||||
"foo@bar.com,foo,sms,Anne Example,,ATT Mobility,Did not like it,Delivered,1943-04-19 12:00:00\r\n",
|
||||
"foo@bar.com,foo,sms,Anne Example,,ATT Mobility,Did not like it,Delivered,1943-04-19 08:00:00 US/Eastern\r\n", # noqa
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -147,7 +151,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"ATT Mobility",
|
||||
"Did not like it",
|
||||
"Delivered",
|
||||
"1943-04-19 12:00:00",
|
||||
"1943-04-19 08:00:00 US/Eastern",
|
||||
],
|
||||
),
|
||||
(
|
||||
@@ -183,7 +187,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"ATT Mobility",
|
||||
"Did not like it",
|
||||
"Delivered",
|
||||
"1943-04-19 12:00:00",
|
||||
"1943-04-19 08:00:00 US/Eastern",
|
||||
],
|
||||
),
|
||||
(
|
||||
@@ -219,7 +223,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"ATT Mobility",
|
||||
"Did not like it",
|
||||
"Delivered",
|
||||
"1943-04-19 12:00:00",
|
||||
"1943-04-19 08:00:00 US/Eastern",
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -389,3 +393,9 @@ def test_get_errors_for_csv(
|
||||
)
|
||||
== expected_errors
|
||||
)
|
||||
|
||||
|
||||
def test_convert_report_date_to_preferred_timezone():
|
||||
original = "2023-11-16 05:00:00"
|
||||
altered = convert_report_date_to_preferred_timezone(original)
|
||||
assert altered == "2023-11-16 00:00:00 US/Eastern"
|
||||
|
||||
Reference in New Issue
Block a user