mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-02 07:27:35 -04:00
Merge branch 'main' into 2109-build-out-architecture-for-new-about-pages-behind-feature-flag
This commit is contained in:
@@ -161,7 +161,7 @@
|
||||
"filename": "app/config.py",
|
||||
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
|
||||
"is_verified": false,
|
||||
"line_number": 125,
|
||||
"line_number": 123,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@@ -684,5 +684,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2024-11-14T15:53:44Z"
|
||||
"generated_at": "2024-11-21T23:08:45Z"
|
||||
}
|
||||
|
||||
1
.github/workflows/checks.yml
vendored
1
.github/workflows/checks.yml
vendored
@@ -144,6 +144,7 @@ jobs:
|
||||
inputs: requirements.txt
|
||||
ignore-vulns: |
|
||||
PYSEC-2024-60
|
||||
PYSEC-2022-43162
|
||||
- name: Run npm audit
|
||||
run: make npm-audit
|
||||
|
||||
|
||||
1
app/assets/images/alarm.svg
Normal file
1
app/assets/images/alarm.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.2 KiB |
1
app/assets/images/alert.svg
Normal file
1
app/assets/images/alert.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Capa_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><g><g><g><path d="m377.64 347.666c-4.473 0-8.1 3.626-8.1 8.099s3.626 8.1 8.1 8.1c4.473 0 8.099-3.626 8.099-8.1s-3.626-8.099-8.099-8.099z"/><path d="m377.716 334.615c4.149 0 7.511-3.363 7.511-7.511v-67.172c0-4.148-3.362-7.511-7.511-7.511-4.148 0-7.511 3.363-7.511 7.511v67.172c0 4.148 3.362 7.511 7.511 7.511z"/><path d="m377.64 219.085c-7.974 0-15.716 1.011-23.105 2.912v-14.937c0-59.921-37.644-111.208-90.522-131.476 2.741-6.491 4.267-13.614 4.267-21.092 0-30.047-24.445-54.492-54.492-54.492s-54.491 24.445-54.491 54.491c0 7.469 1.522 14.586 4.256 21.071-16.063 6.135-30.994 15.219-44.006 26.957-3.081 2.778-3.325 7.528-.547 10.608 2.781 3.081 7.53 3.324 10.608.546 23.118-20.854 53.014-32.339 84.18-32.339 69.324 0 125.725 56.4 125.725 125.725v20.222c-32.217 14.573-54.688 47.021-54.688 84.618 0 11.997 2.288 23.47 6.45 34.005h-203.212v-138.845c0-24.475 7.036-48.196 20.346-68.599 2.267-3.474 1.288-8.128-2.187-10.394-3.474-2.266-8.129-1.288-10.394 2.186-14.907 22.851-22.787 49.41-22.787 76.807v143.829l-28.543 37.616c-1.903 2.506-2.952 5.62-2.952 8.768v27.183c0 7.996 6.505 14.501 14.501 14.501h94.92c-.468 3.102-.719 6.274-.719 9.504 0 35.036 28.504 63.541 63.541 63.541 35.036 0 63.541-28.504 63.541-63.541 0-3.232-.263-6.402-.735-9.504h29.487c4.149 0 7.511-3.363 7.511-7.511s-3.362-7.511-7.511-7.511h-249.514v-26.486l27.713-36.521h214.585c15.307 24.506 41.72 41.39 72.142 43.548v19.459h-29.946c-4.148 0-7.511 3.363-7.511 7.511s3.362 7.511 7.511 7.511h30.467c7.996 0 14.5-6.505 14.5-14.501v-20.125c47.261-4.255 84.425-44.082 84.425-92.431 0-51.178-41.636-92.814-92.814-92.814zm-127.992-148.137c-11.454-3.02-23.471-4.636-35.86-4.636-12.217 0-24.259 1.583-35.863 4.634-2.311-5.012-3.607-10.584-3.607-16.455 0-21.764 17.706-39.469 39.469-39.469s39.469 17.706 39.469 39.469c.002 5.873-1.295 11.445-3.608 16.457zm-83.427 368.007h95.144c.616 3.074.942 6.251.942 9.504 0 26.753-21.765 48.519-48.519 48.519s-48.519-21.766-48.519-48.519c.001-3.254.335-6.429.952-9.504zm211.419-49.263c-42.895 0-77.793-34.898-77.793-77.793s34.897-77.793 77.793-77.793 77.793 34.898 77.793 77.793c-.001 42.895-34.898 77.793-77.793 77.793z"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
app/assets/images/calendar.svg
Normal file
1
app/assets/images/calendar.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.0 KiB |
@@ -898,7 +898,7 @@ li.linked-card:hover svg,
|
||||
display: block;
|
||||
}
|
||||
|
||||
.about-icon-list {
|
||||
.icon-list {
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
@@ -908,10 +908,6 @@ li.linked-card:hover svg,
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.usa-icon-list__content{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.indented-paragraph {
|
||||
margin-left: calc(24px + 4px);
|
||||
margin-top: 4px;
|
||||
|
||||
@@ -91,9 +91,7 @@ class Config(object):
|
||||
getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true"
|
||||
)
|
||||
|
||||
FEATURE_ABOUT_PAGE_ENABLED = (
|
||||
getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
|
||||
)
|
||||
FEATURE_ABOUT_PAGE_ENABLED = getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
|
||||
|
||||
|
||||
def _s3_credentials_from_env(bucket_prefix):
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
from flask import abort, current_app, redirect, render_template, request, url_for
|
||||
from flask import abort, current_app, jsonify, redirect, render_template, request, url_for
|
||||
|
||||
import os
|
||||
import secrets
|
||||
from urllib.parse import unquote
|
||||
|
||||
from flask_login import current_user
|
||||
|
||||
from app import status_api_client
|
||||
@@ -17,19 +22,28 @@ from app.utils.user import user_is_logged_in
|
||||
# Hook to check for feature flags
|
||||
@main.before_request
|
||||
def check_feature_flags():
|
||||
if (
|
||||
request.path.startswith("/guides/best-practices")
|
||||
and not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED", False)
|
||||
if request.path.startswith("/guides/best-practices") and not current_app.config.get(
|
||||
"FEATURE_BEST_PRACTICES_ENABLED", False
|
||||
):
|
||||
abort(404)
|
||||
|
||||
if (
|
||||
request.path.startswith("/about")
|
||||
and not current_app.config.get("FEATURE_ABOUT_PAGE_ENABLED", False)
|
||||
if request.path.startswith("/about") and not current_app.config.get(
|
||||
"FEATURE_ABOUT_PAGE_ENABLED", False
|
||||
):
|
||||
abort(404)
|
||||
|
||||
|
||||
@main.route("/test/feature-flags")
|
||||
def test_feature_flags():
|
||||
return jsonify(
|
||||
{
|
||||
"FEATURE_BEST_PRACTICES_ENABLED": current_app.config[
|
||||
"FEATURE_BEST_PRACTICES_ENABLED"
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@main.route("/")
|
||||
def index():
|
||||
if current_user and current_user.is_authenticated:
|
||||
@@ -249,6 +263,7 @@ def benchmark_performance():
|
||||
)
|
||||
|
||||
|
||||
@main.route("/using-notify/guidance")
|
||||
@main.route("/guides/using-notify/guidance")
|
||||
@user_is_logged_in
|
||||
def guidance_index():
|
||||
@@ -269,6 +284,22 @@ def about_notify():
|
||||
)
|
||||
|
||||
|
||||
@main.route("/about/security")
|
||||
def about_security():
|
||||
return render_template(
|
||||
"views/about/security.html",
|
||||
navigation_links=about_notify_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/about/why-text-messaging")
|
||||
def why_text_messaging():
|
||||
return render_template(
|
||||
"views/about/why-text-messaging.html",
|
||||
navigation_links=about_notify_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/using-notify/guidance/create-and-send-messages")
|
||||
@user_is_logged_in
|
||||
def create_and_send_messages():
|
||||
|
||||
@@ -110,7 +110,31 @@ def best_practices_nav():
|
||||
def about_notify_nav():
|
||||
return [
|
||||
{
|
||||
"name": "About notify",
|
||||
"name": "About Notify",
|
||||
"link": "main.about_notify",
|
||||
"sub_navigation_items": [
|
||||
{
|
||||
"name": "Why text messaging",
|
||||
"link": "main.why_text_messaging",
|
||||
"sub_sub_navigation_items": [
|
||||
{
|
||||
"name": "Reach people using a common method",
|
||||
"link": "main.why_text_messaging#reach-people-using-a-common-method",
|
||||
},
|
||||
{
|
||||
"name": "Improve customer experience",
|
||||
"link": "main.why_text_messaging#improve-customer-experience",
|
||||
},
|
||||
{
|
||||
"name": "What texting is best for",
|
||||
"link": "main.why_text_messaging#what-texting-is-best-for",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Security",
|
||||
"link": "main.about_security",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -53,7 +53,7 @@ class HeaderNavigation(Navigation):
|
||||
"establish_trust",
|
||||
"write_for_action",
|
||||
"multiple_languages",
|
||||
"benchmark_performance"
|
||||
"benchmark_performance",
|
||||
},
|
||||
"using_notify": {
|
||||
"get_started",
|
||||
|
||||
@@ -66,7 +66,20 @@
|
||||
<ul class="usa-sidenav__sublist" role="menu">
|
||||
{% for sub_item in item.sub_navigation_items %}
|
||||
<li role="menuitem">
|
||||
<a href="{{ url_for(sub_item.link.split('#')[0]) }}#{{ sub_item.link.split('#')[1] }}">{{ sub_item.name }}</a>
|
||||
<a href="{{ url_for(sub_item.link.split('#')[0]) }}#{{ sub_item.link.split('#')[1] }}">
|
||||
{{ sub_item.name }}
|
||||
</a>
|
||||
{% if sub_item.sub_sub_navigation_items %}
|
||||
<ul class="usa-sidenav__sublist usa-sidenav__sub-sublist" role="menu">
|
||||
{% for sub_sub_item in sub_item.sub_sub_navigation_items %}
|
||||
<li role="menuitem">
|
||||
<a href="{{ url_for(sub_sub_item.link.split('#')[0]) }}#{{ sub_sub_item.link.split('#')[1] }}">
|
||||
{{ sub_sub_item.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<span class="folder-heading-folder">{{ folder.name }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{{ url_for('.choose_template', service_id=service_id, template_type=template_type) }}" title="Templates" class="usa-link {% if loop.length > 2 %}folder-heading-folder-root-truncated{% endif %}">Templates</a>
|
||||
<a href="{{ url_for('.choose_template', service_id=service_id, template_type=template_type) }}" class="usa-link {% if loop.length > 2 %}folder-heading-folder-root-truncated{% endif %}">Templates</a>
|
||||
{% endif %}
|
||||
{% if not loop.last %}{{ folder_path_separator() }}{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
|
||||
<div class="ajax-block-container" aria-labelledby='pill-selected-item' role="region">
|
||||
<div class="ajax-block-container" role="region">
|
||||
{% if job.scheduled %}
|
||||
|
||||
<p class="usa-body">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% set page_title = "About notify" %}
|
||||
{% set page_title = "About Notify" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{page_title}}
|
||||
@@ -17,8 +17,9 @@
|
||||
<li>Meet people where they are</li>
|
||||
<li>More effectively deliver program outcomes</li>
|
||||
<li>Save administrative costs</li>
|
||||
<li>Implement <a href="https://digital.gov/resources/delivering-digital-first-public-experience/"
|
||||
target="_blank">21st Century IDEA</a> and other directives</li>
|
||||
<li>Implement <a class="use-link usa-link--external"
|
||||
href="https://digital.gov/resources/delivering-digital-first-public-experience/" target="_blank">21st Century
|
||||
IDEA</a> and other directives</li>
|
||||
</ul>
|
||||
<p>Notify.gov is an easy-to-use, web-based platform. It requires no technical expertise or system integration — users
|
||||
can create an account and get started within minutes. We take the security and privacy of messaging data seriously
|
||||
@@ -56,9 +57,9 @@
|
||||
<ul class="usa-icon-list">
|
||||
{% for item in product_highlights %}
|
||||
<li class="usa-icon-list__item">
|
||||
<div class="usa-icon-list__content">
|
||||
<div class="usa-icon-list__content padding-left-0">
|
||||
<div class="usa-icon-list__icon display-flex flex-align-start">
|
||||
<svg aria-hidden="true" focusable="false" role="img" class="about-icon-list">
|
||||
<svg aria-hidden="true" focusable="false" role="img" class="icon-list">
|
||||
<use xlink:href="{{ asset_url('img/sprite.svg') }}{{ item.svg_src }}"></use>
|
||||
</svg>
|
||||
<b>{{item.card_heading}}</b>
|
||||
@@ -68,10 +69,8 @@
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p><a href="/join-notify">See if Notify is right for you</a></p>
|
||||
<p>Notify.gov is a product of the <a href="#" target="_blank">Public Benefits Studio</a>, a product accelerator inside
|
||||
<p><a href="#">See if Notify is right for you</a></p>
|
||||
<p>Notify.gov is a product of the <a href="#">Public Benefits Studio</a>, a product accelerator inside
|
||||
the federal government. </p>
|
||||
|
||||
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
66
app/templates/views/about/security.html
Normal file
66
app/templates/views/about/security.html
Normal file
@@ -0,0 +1,66 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% set page_title = "Security" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{page_title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
<!-- {% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} -->
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base">Notify.gov is built for the needs of government agencies with fundamental system
|
||||
security processes in place to:
|
||||
</p>
|
||||
<ul>
|
||||
<li>protect user data</li>
|
||||
<li>keep systems secure</li>
|
||||
<li>manage risks around information</li>
|
||||
</ul>
|
||||
<p>
|
||||
Notify.gov operates under a full three-year <a class="use-link usa-link--external"
|
||||
href="https://digital.gov/resources/an-introduction-to-ato/" target="_blank">Authority-to-Operate (ATO)</a>. This
|
||||
federal security authorization process leverages security
|
||||
controls provided by National Institute of Standards and Technology (NIST).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Our infrastructure runs on <a class="use-link usa-link--external" href="https://www.cloud.gov/"
|
||||
target="_blank">cloud.gov</a> and utilizes several
|
||||
services through Amazon Web
|
||||
Services (AWS), including <a class="use-link usa-link--external" href="https://aws.amazon.com/sns/" target="_blank">
|
||||
AWS SNS </a> for sending SMS
|
||||
messages.
|
||||
</p>
|
||||
<p>For more information about the Notify.gov infrastructure, contact us at <a
|
||||
href="mailto:notify-support@gsa.gov">notify-support@gsa.gov</a>.</p>
|
||||
<h2>Data</h2>
|
||||
<p>
|
||||
On Notify.gov, data is encrypted both in transit and at rest. To send a message, agencies upload a spreadsheet of
|
||||
phone numbers and other necessary data from their existing data management system.
|
||||
</p>
|
||||
<p>
|
||||
Notify.gov is not a system of record, so it does not have a System of Records Notice (SORN). Agencies are
|
||||
responsible for managing their data outside of Notify.gov.
|
||||
</p>
|
||||
<h3>Data retention</h3>
|
||||
<p>
|
||||
Any data uploads that have recipient data are held for seven calendar days; personally identifiable information
|
||||
(PII) is never stored in Notify’s database.
|
||||
</p>
|
||||
<h2>Multi-Factor Authentication</h2>
|
||||
<p>
|
||||
Notify.gov uses <a class="use-link usa-link--external" href="https://login.gov/what-is-login/"
|
||||
target="_blank">Login.gov</a> for enhanced security.
|
||||
Login.gov is an extra layer of security created by the government that uses multi-factor authentication and stronger
|
||||
passwords to protect your account.
|
||||
</p>
|
||||
<p>
|
||||
To access Notify.gov, users will use a Login.gov account associated with their agency (.gov) email with one of the
|
||||
<a class="use-link usa-link--external" href="https://login.gov/help/get-started/authentication-methods/"
|
||||
target="_blank">multi-factor authentication
|
||||
methods</a> offered through Login.gov.
|
||||
</p>
|
||||
</section>
|
||||
{% endblock %}
|
||||
86
app/templates/views/about/why-text-messaging.html
Normal file
86
app/templates/views/about/why-text-messaging.html
Normal file
@@ -0,0 +1,86 @@
|
||||
{% extends "base.html" %}
|
||||
{% set page_title = "Why text messaging" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{page_title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
<!-- {% with title=page_title, parent_title="About", url="main.why_text_messaging" %}{% include
|
||||
"components/best-practices/nav_breadcrumb.html" %}{% endwith %} -->
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<h2 id="reach-people-using-a-common-method">Reach people using a common method</h2>
|
||||
<p>
|
||||
Confusing or <a class="use-link usa-link--external"
|
||||
href="https://kffhealthnews.org/news/tougher-returned-mail-policies-add-to-medicaid-enrollment-drop/"
|
||||
target="_blank">unreceived notifications</a> are one of the largest barriers to people getting and keeping
|
||||
benefits. The typical ways the government communicates with people often fall short. Low income households are more
|
||||
likely to experience housing instability, which means paper mail, already slow, can easily be missed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a class="use-link usa-link--external"
|
||||
href="https://www.pewresearch.org/internet/fact-sheet/mobile/?tabItem=64e32376-5a21-4b1d-8f8b-5f92406db984"
|
||||
target="_blank">Pew Research shows that nearly all adults in the US have a cell phone.</a> Reliance on smartphones
|
||||
for online access is especially common among Americans with lower household incomes and those with lower levels of
|
||||
formal education. Of those earning less than $30,000 a year, 28% say their mobile phone is the sole method to
|
||||
digitally connect.
|
||||
</p>
|
||||
<p>
|
||||
This means that for many people who rely on government services, cell phones may be the most reliable place to meet
|
||||
people where they already are.
|
||||
</p>
|
||||
<h2 id="improve-customer-experience">Improve customer experience</h2>
|
||||
<p>
|
||||
Text messages can deliver concise information and drive an audience to take action quickly. Timely reminders sent
|
||||
via text message have been proven to decrease re-enrollment churn and save money for administering agencies.
|
||||
</p>
|
||||
<p>
|
||||
Texting not only helps programs reach people using a nearly-universal communication method, it is a cost effective
|
||||
way to do so. With Notify.gov <a href="#">you can get started for free</a>, allowing you to try out
|
||||
texting to complement your existing communications and outreach strategies.
|
||||
</p>
|
||||
<h2 id="what-texting-is-best-for">What texting is best for</h2>
|
||||
<p>
|
||||
Agencies, like you, are already using Notify.gov to text about the following programs.
|
||||
</p>
|
||||
{% set card_contents = [
|
||||
{
|
||||
"image_src": asset_url('images/calendar.svg'),
|
||||
"card_heading": "Reminders",
|
||||
"p_text": "In a text bubble // Your Quality Control food phone interview is on ((date)) at ((time)). Failure to
|
||||
attend may lead to closure of your benefits. Call 1-800-222-3333 with questions.",
|
||||
"alt_text": "reminder text example"
|
||||
},
|
||||
{
|
||||
"image_src": asset_url('images/alert.svg'),
|
||||
"card_heading": "Alerts to take action",
|
||||
"p_text": "In a text bubble // Your household's Medicaid coverage is expiring. To keep getting Medicaid, you must
|
||||
complete your renewal by ((date)). You can renew online at dhs.state.gov…",
|
||||
"alt_text": "alerts text example"
|
||||
},
|
||||
{
|
||||
"image_src": asset_url('images/alarm.svg'),
|
||||
"card_heading": "Important status updates",
|
||||
"p_text": "In a text bubble // Your passport has been issued at the Los Angeles Passport Agency. Please come to the
|
||||
desk between 1:30pm and 2:30pm today to pick up your passport…",
|
||||
"alt_text": "status update text example"
|
||||
},
|
||||
] %}
|
||||
{% for item in card_contents %}
|
||||
<div class="radius-lg border-2px maxw-tablet">
|
||||
<div class="grid-row grid-gap-4 padding-4 padding-y-3 flex-align-center">
|
||||
<div class="grid-col flex-3">
|
||||
<p><b>{{item.card_heading}}</b></p>
|
||||
<p>{{item.p_text}}</p>
|
||||
</div>
|
||||
{% if item.image_src %}
|
||||
<img src="{{item.image_src}}" alt="{{ item.alt_text }}" class="height-15" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -103,6 +103,7 @@ def generate_notifications_csv(**kwargs):
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
]
|
||||
for header in original_column_headers:
|
||||
if header.lower() != "phone number":
|
||||
@@ -118,6 +119,7 @@ def generate_notifications_csv(**kwargs):
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
]
|
||||
|
||||
yield ",".join(fieldnames) + "\n"
|
||||
@@ -140,6 +142,7 @@ def generate_notifications_csv(**kwargs):
|
||||
notification["provider_response"],
|
||||
notification["status"],
|
||||
preferred_tz_created_at,
|
||||
notification["carrier"],
|
||||
]
|
||||
for header in original_column_headers:
|
||||
if header.lower() != "phone number":
|
||||
@@ -158,6 +161,7 @@ def generate_notifications_csv(**kwargs):
|
||||
notification["provider_response"],
|
||||
notification["status"],
|
||||
preferred_tz_created_at,
|
||||
notification["carrier"],
|
||||
]
|
||||
yield Spreadsheet.from_rows([map(str, values)]).as_csv_data
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
Navigation.get_endpoint_with_blueprint,
|
||||
{
|
||||
"about_notify",
|
||||
"about_security",
|
||||
"accept_invite",
|
||||
"accept_org_invite",
|
||||
"accessibility_statement",
|
||||
@@ -218,6 +219,7 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"suspend_service",
|
||||
"template_history",
|
||||
"template_usage",
|
||||
"test_feature_flags",
|
||||
"tour_step",
|
||||
"trial_mode",
|
||||
"trial_mode_new",
|
||||
@@ -257,6 +259,7 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"view_template_version",
|
||||
"view_template_versions",
|
||||
"who_its_for",
|
||||
"why_text_messaging",
|
||||
"write_for_action",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -58,6 +58,7 @@ def _get_notifications_csv(
|
||||
"to": recipient,
|
||||
"recipient": recipient,
|
||||
"client_reference": "ref 1234",
|
||||
"carrier": "AT&T Mobility",
|
||||
}
|
||||
for i in range(rows)
|
||||
],
|
||||
@@ -88,15 +89,15 @@ def get_notifications_csv_mock(
|
||||
(
|
||||
None,
|
||||
[
|
||||
"Phone Number,Template,Sent by,Batch File,Carrier Response,Status,Time\n",
|
||||
"8005555555,foo,,,Did not like it,Delivered,1943-04-19 08:00:00 AM US/Eastern\r\n",
|
||||
"Phone Number,Template,Sent by,Batch File,Carrier Response,Status,Time,Carrier\n",
|
||||
"8005555555,foo,,,Did not like it,Delivered,1943-04-19 08:00:00 AM US/Eastern,AT&T Mobility\r\n",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Anne Example",
|
||||
[
|
||||
"Phone Number,Template,Sent by,Batch File,Carrier Response,Status,Time\n",
|
||||
"8005555555,foo,Anne Example,,Did not like it,Delivered,1943-04-19 08:00:00 AM US/Eastern\r\n", # noqa
|
||||
"Phone Number,Template,Sent by,Batch File,Carrier Response,Status,Time,Carrier\n",
|
||||
"8005555555,foo,Anne Example,,Did not like it,Delivered,1943-04-19 08:00:00 AM US/Eastern,AT&T Mobility\r\n", # noqa
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -135,6 +136,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
],
|
||||
[
|
||||
"8005555555",
|
||||
@@ -144,6 +146,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"Did not like it",
|
||||
"Delivered",
|
||||
"1943-04-19 08:00:00 AM US/Eastern",
|
||||
"AT&T Mobility",
|
||||
],
|
||||
),
|
||||
(
|
||||
@@ -159,6 +162,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
@@ -171,6 +175,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"Did not like it",
|
||||
"Delivered",
|
||||
"1943-04-19 08:00:00 AM US/Eastern",
|
||||
"AT&T Mobility",
|
||||
"🐜",
|
||||
"🐝",
|
||||
"🦀",
|
||||
@@ -189,6 +194,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
@@ -201,6 +207,7 @@ def test_generate_notifications_csv_without_job(
|
||||
"Did not like it",
|
||||
"Delivered",
|
||||
"1943-04-19 08:00:00 AM US/Eastern",
|
||||
"AT&T Mobility",
|
||||
"🐜,🐜",
|
||||
"🐝,🐝",
|
||||
"🦀",
|
||||
|
||||
72
tests/end_to_end/test_best_practices_content_pages.py
Normal file
72
tests/end_to_end/test_best_practices_content_pages.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from playwright.sync_api import expect
|
||||
|
||||
from tests.end_to_end.conftest import check_axe_report
|
||||
|
||||
E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
|
||||
|
||||
|
||||
def test_best_practices_side_menu(authenticated_page):
|
||||
page = authenticated_page
|
||||
|
||||
page.goto(f"{E2E_TEST_URI}/best-practices")
|
||||
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
check_axe_report(page)
|
||||
|
||||
response = page.request.get(f"{E2E_TEST_URI}/test/feature-flags")
|
||||
feature_flags = response.json()
|
||||
feature_best_practices_enabled = feature_flags.get("FEATURE_BEST_PRACTICES_ENABLED")
|
||||
|
||||
if feature_best_practices_enabled:
|
||||
page.get_by_role("link", name="Best Practices").click()
|
||||
expect(page).to_have_title(re.compile("Best Practice"))
|
||||
|
||||
page.get_by_role("link", name="Clear goals", exact=True).click()
|
||||
expect(page).to_have_title(re.compile("Establish clear goals"))
|
||||
|
||||
page.get_by_role("link", name="Rules and regulations").click()
|
||||
expect(page).to_have_title(re.compile("Rules and regulations"))
|
||||
|
||||
page.get_by_role("link", name="Establish trust").click()
|
||||
expect(page).to_have_title(re.compile("Establish trust"))
|
||||
|
||||
page.get_by_role("link", name="Write for action").click()
|
||||
expect(page).to_have_title(re.compile("Write texts that provoke"))
|
||||
|
||||
page.get_by_role("link", name="Multiple languages").click()
|
||||
expect(page).to_have_title(re.compile("Text in multiple languages"))
|
||||
|
||||
page.get_by_role("link", name="Benchmark performance").click()
|
||||
expect(page).to_have_title(re.compile("Measuring performance with"))
|
||||
|
||||
parent_link = page.get_by_role("link", name="Establish trust")
|
||||
parent_link.hover()
|
||||
|
||||
submenu_item = page.get_by_role("link", name=re.compile("Get the word out"))
|
||||
submenu_item.click()
|
||||
|
||||
expect(page).to_have_url(re.compile(r"#get-the-word-out"))
|
||||
|
||||
anchor_target = page.locator("#get-the-word-out")
|
||||
expect(anchor_target).to_be_visible()
|
||||
anchor_target.click()
|
||||
|
||||
|
||||
def test_breadcrumbs_best_practices(authenticated_page):
|
||||
page = authenticated_page
|
||||
|
||||
page.goto(f"{E2E_TEST_URI}/best-practices")
|
||||
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
check_axe_report(page)
|
||||
|
||||
response = page.request.get(f"{E2E_TEST_URI}/test/feature-flags")
|
||||
feature_flags = response.json()
|
||||
feature_best_practices_enabled = feature_flags.get("FEATURE_BEST_PRACTICES_ENABLED")
|
||||
|
||||
if feature_best_practices_enabled:
|
||||
page.get_by_role("link", name="Clear goals", exact=True).click()
|
||||
page.locator("ol").get_by_role("link", name="Best Practices").click()
|
||||
Reference in New Issue
Block a user