Merge branch 'main' into 2104-join-notify

This commit is contained in:
Beverly Nguyen
2024-12-04 14:16:31 -08:00
38 changed files with 752 additions and 361 deletions
+2 -2
View File
@@ -161,7 +161,7 @@
"filename": "app/config.py", "filename": "app/config.py",
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc", "hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
"is_verified": false, "is_verified": false,
"line_number": 125, "line_number": 123,
"is_secret": false "is_secret": false
} }
], ],
@@ -684,5 +684,5 @@
} }
] ]
}, },
"generated_at": "2024-11-14T15:53:44Z" "generated_at": "2024-11-21T23:08:45Z"
} }
+1
View File
@@ -144,6 +144,7 @@ jobs:
inputs: requirements.txt inputs: requirements.txt
ignore-vulns: | ignore-vulns: |
PYSEC-2024-60 PYSEC-2024-60
PYSEC-2022-43162
- name: Run npm audit - name: Run npm audit
run: make npm-audit run: make npm-audit
+35 -5
View File
@@ -1,8 +1,9 @@
import os import os
import pathlib import pathlib
import secrets
from functools import partial from functools import partial
from time import monotonic from time import monotonic
from urllib.parse import urlparse, urlunparse from urllib.parse import unquote, urlparse, urlunparse
import jinja2 import jinja2
from flask import ( from flask import (
@@ -114,6 +115,7 @@ from notifications_utils.formatters import (
get_lines_with_normalised_whitespace, get_lines_with_normalised_whitespace,
) )
from notifications_utils.recipients import format_phone_number_human_readable from notifications_utils.recipients import format_phone_number_human_readable
from notifications_utils.url_safe_token import generate_token
login_manager = LoginManager() login_manager = LoginManager()
csrf = CSRFProtect() csrf = CSRFProtect()
@@ -168,10 +170,38 @@ def create_app(application):
@application.context_processor @application.context_processor
def inject_feature_flags(): def inject_feature_flags():
feature_best_practices_enabled = application.config[ feature_best_practices_enabled = application.config.get("FEATURE_BEST_PRACTICES_ENABLED", False)
"FEATURE_BEST_PRACTICES_ENABLED" feature_about_page_enabled = application.config.get("FEATURE_ABOUT_PAGE_ENABLED", False)
] return dict(
return dict(FEATURE_BEST_PRACTICES_ENABLED=feature_best_practices_enabled) FEATURE_BEST_PRACTICES_ENABLED=feature_best_practices_enabled,
FEATURE_ABOUT_PAGE_ENABLED=feature_about_page_enabled,
)
@application.context_processor
def inject_initial_signin_url():
ttl = 24 * 60 * 60
# make and store the state
state = generate_token(
str(request.remote_addr),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
state_key = f"login-state-{unquote(state)}"
redis_client.set(state_key, state, ex=ttl)
# make and store the nonce
nonce = secrets.token_urlsafe()
nonce_key = f"login-nonce-{unquote(nonce)}"
redis_client.set(nonce_key, nonce, ex=ttl)
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
if url is not None:
url = url.replace("NONCE", nonce)
url = url.replace("STATE", state)
return {'initial_signin_url': url}
notify_environment = os.environ["NOTIFY_ENVIRONMENT"] notify_environment = os.environ["NOTIFY_ENVIRONMENT"]
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.2 KiB

+1
View 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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

@@ -676,28 +676,28 @@ details form {
margin-top: 0; margin-top: 0;
} }
ol.best-practices-list { ol.guides-list {
counter-reset: item; counter-reset: item;
list-style-type: none; list-style-type: none;
padding-left: 0; padding-left: 0;
} }
ol.best-practices-list.set-two { ol.guides-list.set-two {
counter-reset: item 6; counter-reset: item 6;
} }
ol.best-practices-list.set-three { ol.guides-list.set-three {
counter-reset: item 10; counter-reset: item 10;
} }
ol.best-practices-list li { ol.guides-list li {
counter-increment: item; counter-increment: item;
margin-bottom: 15px; margin-bottom: 15px;
position: relative; position: relative;
padding-left: 40px; padding-left: 40px;
} }
ol.best-practices-list li::before { ol.guides-list li::before {
content: counter(item); content: counter(item);
background-color: #005ea2; background-color: #005ea2;
color: white; color: white;
@@ -713,11 +713,11 @@ ol.best-practices-list li::before {
top: 0; top: 0;
} }
li.best-practices { li.guides {
padding-bottom: 50px; padding-bottom: 50px;
} }
div.best-practices { div.guides {
height: 400px height: 400px
} }
@@ -820,7 +820,7 @@ $do-dont-top-bar-width: 1;
} }
@media (max-width: 758px) { @media (max-width: 758px) {
.best-practices-flex-container { .guides-flex-container {
flex-direction: column; flex-direction: column;
} }
} }
@@ -899,6 +899,7 @@ li.linked-card:hover svg,
} }
.icon-list { .icon-list {
display: flex;
width: 24px; width: 24px;
height: 24px; height: 24px;
padding: 2px 1px; padding: 2px 1px;
+1 -3
View File
@@ -91,9 +91,7 @@ class Config(object):
getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true" getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true"
) )
FEATURE_ABOUT_PAGE_ENABLED = ( FEATURE_ABOUT_PAGE_ENABLED = getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
)
def _s3_credentials_from_env(bucket_prefix): def _s3_credentials_from_env(bucket_prefix):
+54 -49
View File
@@ -1,11 +1,15 @@
import os from flask import (
import secrets abort,
from urllib.parse import unquote current_app,
jsonify,
from flask import abort, current_app, redirect, render_template, request, url_for redirect,
render_template,
request,
url_for,
)
from flask_login import current_user from flask_login import current_user
from app import redis_client, status_api_client from app import status_api_client
from app.formatters import apply_html_class, convert_markdown_template from app.formatters import apply_html_class, convert_markdown_template
from app.main import main from app.main import main
from app.main.views.pricing import CURRENT_SMS_RATE from app.main.views.pricing import CURRENT_SMS_RATE
@@ -16,55 +20,42 @@ from app.main.views.sub_navigation_dictionaries import (
using_notify_nav, using_notify_nav,
) )
from app.utils.user import user_is_logged_in from app.utils.user import user_is_logged_in
from notifications_utils.url_safe_token import generate_token
# Hook to check for feature flags # Hook to check for feature flags
@main.before_request @main.before_request
def check_feature_flags(): def check_feature_flags():
if ( if request.path.startswith("/guides") and not current_app.config.get(
request.path.startswith("/guides/best-practices") "FEATURE_BEST_PRACTICES_ENABLED", False
and not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED", False)
): ):
abort(404) abort(404)
if ( if request.path.startswith("/about") and not current_app.config.get(
request.path.startswith("/about") "FEATURE_ABOUT_PAGE_ENABLED", False
and not current_app.config.get("FEATURE_ABOUT_PAGE_ENABLED", False)
): ):
abort(404) 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("/") @main.route("/")
def index(): def index():
if current_user and current_user.is_authenticated: if current_user and current_user.is_authenticated:
return redirect(url_for("main.choose_account")) return redirect(url_for("main.choose_account"))
ttl = 24 * 60 * 60
# make and store the state
state = generate_token(
str(request.remote_addr),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
state_key = f"login-state-{unquote(state)}"
redis_client.set(state_key, state, ex=ttl)
# make and store the nonce
nonce = secrets.token_urlsafe()
nonce_key = f"login-nonce-{unquote(nonce)}"
redis_client.set(nonce_key, nonce, ex=ttl)
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
if url is not None:
url = url.replace("NONCE", nonce)
url = url.replace("STATE", state)
return render_template( return render_template(
"views/signedout.html", "views/signedout.html",
sms_rate=CURRENT_SMS_RATE, sms_rate=CURRENT_SMS_RATE,
counts=status_api_client.get_count_of_live_services_and_organizations(), counts=status_api_client.get_count_of_live_services_and_organizations()
initial_signin_url=url,
) )
@@ -216,61 +207,61 @@ def trial_mode_new():
@user_is_logged_in @user_is_logged_in
def best_practices(): def best_practices():
return render_template( return render_template(
"views/best-practices/best-practices.html", "views/guides/best-practices.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@main.route("/guides/best-practices/clear-goals") @main.route("/guides/clear-goals")
@user_is_logged_in @user_is_logged_in
def clear_goals(): def clear_goals():
return render_template( return render_template(
"views/best-practices/clear-goals.html", "views/guides/clear-goals.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@main.route("/guides/best-practices/rules-and-regulations") @main.route("/guides/rules-and-regulations")
@user_is_logged_in @user_is_logged_in
def rules_and_regulations(): def rules_and_regulations():
return render_template( return render_template(
"views/best-practices/rules-and-regulations.html", "views/guides/rules-and-regulations.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@main.route("/guides/best-practices/establish-trust") @main.route("/guides/establish-trust")
@user_is_logged_in @user_is_logged_in
def establish_trust(): def establish_trust():
return render_template( return render_template(
"views/best-practices/establish-trust.html", "views/guides/establish-trust.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@main.route("/guides/best-practices/write-for-action") @main.route("/guides/write-for-action")
@user_is_logged_in @user_is_logged_in
def write_for_action(): def write_for_action():
return render_template( return render_template(
"views/best-practices/write-for-action.html", "views/guides/write-for-action.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@main.route("/guides/best-practices/multiple-languages") @main.route("/guides/multiple-languages")
@user_is_logged_in @user_is_logged_in
def multiple_languages(): def multiple_languages():
return render_template( return render_template(
"views/best-practices/multiple-languages.html", "views/guides/multiple-languages.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@main.route("/guides/best-practices/benchmark-performance") @main.route("/guides/benchmark-performance")
@user_is_logged_in @user_is_logged_in
def benchmark_performance(): def benchmark_performance():
return render_template( return render_template(
"views/best-practices/benchmark-performance.html", "views/guides/benchmark-performance.html",
navigation_links=best_practices_nav(), navigation_links=best_practices_nav(),
) )
@@ -294,12 +285,26 @@ def about_notify():
navigation_links=about_notify_nav(), navigation_links=about_notify_nav(),
) )
@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("/about/join-notify") @main.route("/about/join-notify")
def join_notify(): def join_notify():
return render_template( return render_template(
"views/about/join-notify.html", "views/about/join-notify.html",
navigation_links=about_notify_nav(),
) )
+41 -40
View File
@@ -1,3 +1,6 @@
from flask import current_app
def features_nav(): def features_nav():
return [ return [
{ {
@@ -22,46 +25,20 @@ def features_nav():
def using_notify_nav(): def using_notify_nav():
return [ nav_items = [
{ {"name": "Get started", "link": "main.get_started"},
"name": "Get started", {"name": "Guides", "link": "main.best_practices"},
"link": "main.get_started", {"name": "Trial mode", "link": "main.trial_mode_new"},
}, {"name": "Tracking usage", "link": "main.pricing"},
{ {"name": "Delivery Status", "link": "main.message_status"},
"name": "Guides", {"name": "Guidance", "link": "main.guidance_index"},
"link": "main.best_practices",
},
{
"name": "Trial mode",
"link": "main.trial_mode_new",
},
{
"name": "Tracking usage",
"link": "main.pricing",
},
{
"name": "Delivery status",
"link": "main.message_status",
},
{
"name": "Guidance",
"link": "main.guidance_index",
# "sub_navigation_items": [
# {
# "name": "Formatting",
# "link": "main.edit_and_format_messages",
# },
# {
# "name": "Send files by email",
# "link": "main.send_files_by_email",
# },
# ]
# {
# "name": "API documentation",
# "link": "main.documentation",
# },
},
] ]
if not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED"):
nav_items = [
item for item in nav_items if item["link"] != "main.best_practices"
]
return nav_items
def best_practices_nav(): def best_practices_nav():
@@ -110,8 +87,32 @@ def best_practices_nav():
def about_notify_nav(): def about_notify_nav():
return [ return [
{ {
"name": "About notify", "name": "About Notify",
"link": "main.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",
},
],
}, },
{ {
"name": "Join Notify", "name": "Join Notify",
+1 -1
View File
@@ -53,7 +53,7 @@ class HeaderNavigation(Navigation):
"establish_trust", "establish_trust",
"write_for_action", "write_for_action",
"multiple_languages", "multiple_languages",
"benchmark_performance" "benchmark_performance",
}, },
"using_notify": { "using_notify": {
"get_started", "get_started",
+14 -1
View File
@@ -66,7 +66,20 @@
<ul class="usa-sidenav__sublist" role="menu"> <ul class="usa-sidenav__sublist" role="menu">
{% for sub_item in item.sub_navigation_items %} {% for sub_item in item.sub_navigation_items %}
<li role="menuitem"> <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> </li>
{% endfor %} {% endfor %}
</ul> </ul>
+1 -1
View File
@@ -22,7 +22,7 @@
<span class="folder-heading-folder">{{ folder.name }}</span> <span class="folder-heading-folder">{{ folder.name }}</span>
{% endif %} {% endif %}
{% else %} {% 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 %} {% endif %}
{% if not loop.last %}{{ folder_path_separator() }}{% endif %} {% if not loop.last %}{{ folder_path_separator() }}{% endif %}
{% endif %} {% endif %}
+20 -8
View File
@@ -43,18 +43,29 @@ secondary_navigation.is_selected('settings')},
<header class="usa-header usa-header--extended"> <header class="usa-header usa-header--extended">
<div class="usa-nav-container"> <div class="usa-nav-container">
<div class="usa-navbar"> <div class="usa-navbar">
<div class="usa-logo display-flex flex-align-center flex-justify" id="-logo"> <div class="display-flex flex-align-center flex-justify">
<div class="logo-img display-flex"> <div class="usa-logo display-flex flex-align-center flex-justify" id="-logo">
<a href="/"> <div class="logo-img display-flex">
<span class="usa-sr-only">Notify.gov logo</span> <a href="/">
<img src="{{ (asset_path | default('/static')) + 'images/notify-logo.svg' }}" alt="Notify.gov logo" <span class="usa-sr-only">Notify.gov logo</span>
class="usa-flag-logo margin-right-1"> <img src="{{ (asset_path | default('/static')) + 'images/notify-logo.svg' }}" alt="Notify.gov logo"
class="usa-flag-logo margin-right-1">
</a>
</div>
{% if navigation %}
<button type="button" class="usa-menu-btn">Menu</button>
{% endif %}
</div>
{% if not current_user.is_authenticated and FEATURE_ABOUT_PAGE_ENABLED and request.path == '/about'%}
<div class="usa-nav__login">
<a class="usa-button usa-button login-button login-button--primary margin-right-2"
href="{{ initial_signin_url }}">Sign
in with <img src="{{ asset_url('images/logo-login.svg') }}" alt="Login.gov logo">
</a> </a>
</div> </div>
{% if navigation %}
<button type="button" class="usa-menu-btn">Menu</button>
{% endif %} {% endif %}
</div> </div>
</div> </div>
<nav aria-label="Primary navigation" class="usa-nav"> <nav aria-label="Primary navigation" class="usa-nav">
<div class="usa-nav__inner"> <div class="usa-nav__inner">
@@ -89,6 +100,7 @@ secondary_navigation.is_selected('settings')},
{% endif %} {% endif %}
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>
</div> </div>
@@ -1,8 +1,12 @@
{% macro breadcrumb(title, parent_menu_title, url) %}
<nav class="navigation-service usa-breadcrumb padding-top-0"> <nav class="navigation-service usa-breadcrumb padding-top-0">
<ol class="usa-breadcrumb__list"> <ol class="usa-breadcrumb__list">
<li class="usa-breadcrumb__list-item"> <li class="usa-breadcrumb__list-item">
<span class="usa-breadcrumb__label"><a href="{{ url_for('.best_practices') }}" <span class="usa-breadcrumb__label">
class="usa-link navigation-organization-link">Best Practices</a></span> <a href="{{ url_for(url) }}" class="usa-link navigation-organization-link">
{{ parent_menu_title }}
</a>
</span>
</li> </li>
{% if title %} {% if title %}
<li class="usa-breadcrumb__list-item"> <li class="usa-breadcrumb__list-item">
@@ -11,3 +15,4 @@
{% endif %} {% endif %}
</ol> </ol>
</nav> </nav>
{% endmacro %}
@@ -2,7 +2,7 @@
{% from "components/page-footer.html" import page_footer %} {% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %} {% 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 %} {% if job.scheduled %}
<p class="usa-body"> <p class="usa-body">
+6 -8
View File
@@ -1,13 +1,12 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set page_title = "About notify" %} {% set page_title = "About Notify" %}
{% block per_page_title %} {% block per_page_title %}
{{page_title}} {{page_title}}
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
<!-- {% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} -->
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p>Notify.gov is a text messaging service built by and for the government. We help agencies communicate more <p>Notify.gov is a text messaging service built by and for the government. We help agencies communicate more
@@ -17,8 +16,9 @@
<li>Meet people where they are</li> <li>Meet people where they are</li>
<li>More effectively deliver program outcomes</li> <li>More effectively deliver program outcomes</li>
<li>Save administrative costs</li> <li>Save administrative costs</li>
<li>Implement <a href="https://digital.gov/resources/delivering-digital-first-public-experience/" <li>Implement <a class="use-link usa-link--external"
target="_blank">21st Century IDEA</a> and other directives</li> href="https://digital.gov/resources/delivering-digital-first-public-experience/" target="_blank">21st Century
IDEA</a> and other directives</li>
</ul> </ul>
<p>Notify.gov is an easy-to-use, web-based platform. It requires no technical expertise or system integration — users <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 can create an account and get started within minutes. We take the security and privacy of messaging data seriously
@@ -68,10 +68,8 @@
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
<p><a href="/about/join-notify">See if Notify is right for you</a></p> <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>Notify.gov is a product of the <a href="#">Public Benefits Studio</a>, a product accelerator inside
the federal government. </p> the federal government. </p>
</section> </section>
{% endblock %} {% endblock %}
+68
View File
@@ -0,0 +1,68 @@
{% extends "base.html" %}
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% set page_title = "Security" %}
{% block per_page_title %}
{{page_title}}
{% endblock %}
{% block content_column_content %}
{{ breadcrumbs.breadcrumb(page_title, "About", "main.about_notify") }}
<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 Notifys 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 %}
@@ -0,0 +1,87 @@
{% extends "base.html" %}
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% set page_title = "Why text messaging" %}
{% block per_page_title %}
{{page_title}}
{% endblock %}
{% block content_column_content %}
{{ breadcrumbs.breadcrumb(page_title, "About", "main.about_notify") }}
<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 %}
@@ -1,4 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% set page_title = "Measuring performance with benchmarking" %} {% set page_title = "Measuring performance with benchmarking" %}
@@ -7,7 +8,8 @@
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} {{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p class="font-sans-lg text-base">Learn how effective your texting program can be.</p> <p class="font-sans-lg text-base">Learn how effective your texting program can be.</p>
@@ -19,7 +21,7 @@
</p> </p>
<h2>What other texting studies have found</h2> <h2>What other texting studies have found</h2>
<p> <p>
When the <a When the <a class="use-link usa-link--external"
href="https://www.cbpp.org/research/food-assistance/targeted-text-message-outreach-can-increase-wic-enrollment-pilots-show" href="https://www.cbpp.org/research/food-assistance/targeted-text-message-outreach-can-increase-wic-enrollment-pilots-show"
target="_blank">Center on Budget and Policy Priorities</a> studied WIC, they found key learnings about the target="_blank">Center on Budget and Policy Priorities</a> studied WIC, they found key learnings about the
quantity of messages delivered, how people engage with messages, and how they take action. quantity of messages delivered, how people engage with messages, and how they take action.
@@ -78,7 +80,8 @@
</div> </div>
<p> <p>
The <a href="https://codeforamerica.org/resources/texting-playbook/" target="_blank">Code for Americas Texting The <a class="use-link usa-link--external" href="https://codeforamerica.org/resources/texting-playbook/"
target="_blank">Code for Americas Texting
Playbook</a> Playbook</a>
reported specific learnings around appointment reminders, completing reported specific learnings around appointment reminders, completing
document submission, and maintenance reminders. document submission, and maintenance reminders.
@@ -1,11 +1,12 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set page_title = "Best Practices" %}
{% block per_page_title %} {% block per_page_title %}
Best Practices {{page_title}}
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
<section class="usa-prose"> <section class="usa-prose">
<h1>Best Practices</h1> <h1>Best Practices</h1>
<p class="font-sans-lg text-base">For texting the public</p> <p class="font-sans-lg text-base">For texting the public</p>
@@ -23,41 +24,41 @@ Best Practices
"svg_src": "goal", "svg_src": "goal",
"card_heading": "Establish clear goals", "card_heading": "Establish clear goals",
"p_text": "Start with a singular purpose. Make explicit what you want to achieve.", "p_text": "Start with a singular purpose. Make explicit what you want to achieve.",
"link": "/guides/best-practices/clear-goals" "link": "/guides/clear-goals"
}, },
{ {
"svg_src": "compliant", "svg_src": "compliant",
"card_heading": "Follow rules & regulations", "card_heading": "Follow rules & regulations",
"p_text": "Understand what is required when texting the public.", "p_text": "Understand what is required when texting the public.",
"link": "/guides/best-practices/rules-and-regulations" "link": "/guides/rules-and-regulations"
}, },
{ {
"svg_src": "trust", "svg_src": "trust",
"card_heading": "Establish trust", "card_heading": "Establish trust",
"p_text": "Help your audience anticipate and welcome your texts.", "p_text": "Help your audience anticipate and welcome your texts.",
"link": "/guides/best-practices/establish-trust" "link": "/guides/establish-trust"
}, },
{ {
"svg_src": "runner", "svg_src": "runner",
"card_heading": "Write texts that provoke action", "card_heading": "Write texts that provoke action",
"p_text": "Help your audience know what to do with the information you send.", "p_text": "Help your audience know what to do with the information you send.",
"link": "/guides/best-practices/write-for-action" "link": "/guides/write-for-action"
}, },
{ {
"svg_src": "language", "svg_src": "language",
"card_heading": "Send texts in multiple languages", "card_heading": "Send texts in multiple languages",
"p_text": "What to know as you plan translated texts.", "p_text": "What to know as you plan translated texts.",
"link": "/guides/best-practices/multiple-languages" "link": "/guides/multiple-languages"
}, },
{ {
"svg_src": "chart", "svg_src": "chart",
"card_heading": "Measure performance with benchmarking", "card_heading": "Measure performance with benchmarking",
"p_text": "Learn how effective your texting program can be.", "p_text": "Learn how effective your texting program can be.",
"link": "/guides/best-practices/benchmark-performance" "link": "/guides/benchmark-performance"
} }
] %} ] %}
{% with card_contents=card_contents %}{% include "components/best-practices/cards.html" %}{% {% with card_contents=card_contents %}{% include "components/guides/cards.html" %}{%
endwith %} endwith %}
</section> </section>
@@ -1,4 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% set page_title = "Establish clear goals" %} {% set page_title = "Establish clear goals" %}
@@ -7,7 +8,8 @@
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} {{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p class="font-sans-lg text-base">Start with a singular purpose. Make explicit what you want to achieve.</p> <p class="font-sans-lg text-base">Start with a singular purpose. Make explicit what you want to achieve.</p>
@@ -160,7 +162,7 @@
</div> </div>
<p> <p>
Review your drafted hypothesis with your team to make sure everyone is aligned on your desired goals. A clear and Review your drafted hypothesis with your team to make sure everyone is aligned on your desired goals. A clear and
concise hypothesis can help you decide how to <a href="../best-practices/write-for-action">write text message concise hypothesis can help you decide how to <a href="../guides/write-for-action">write text message
content content
that provokes action</a>. that provokes action</a>.
</p> </p>
@@ -1,5 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/best-practices/circle_number.html" import circle_number %} {% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% from "components/guides/circle_number.html" import circle_number %}
{% set page_title = "Establish trust" %} {% set page_title = "Establish trust" %}
@@ -8,7 +10,8 @@
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} {{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p class="font-sans-lg text-base">Help your audience anticipate and welcome your texts.</p> <p class="font-sans-lg text-base">Help your audience anticipate and welcome your texts.</p>
@@ -38,7 +41,7 @@
<li class="flex-1 width-full height-full padding-bottom-2"> <li class="flex-1 width-full height-full padding-bottom-2">
<div class="usa-card__container border-0"> <div class="usa-card__container border-0">
<p>To reinforce legitimacy, include these key messages in your outreach:</p> <p>To reinforce legitimacy, include these key messages in your outreach:</p>
<ol class="best-practices-list"> <ol class="guides-list">
<li><b>Introduce yourself</b> Give people time to get to know your texting communications before you need <li><b>Introduce yourself</b> Give people time to get to know your texting communications before you need
direct action from them</li> direct action from them</li>
<li><b>Phone number</b> Note the sending phone number your texts will come from</li> <li><b>Phone number</b> Note the sending phone number your texts will come from</li>
@@ -79,7 +82,7 @@
<ul class="usa-card-group flex-1 flex-wrap padding-top-2"> <ul class="usa-card-group flex-1 flex-wrap padding-top-2">
<li class="flex-1 width-full height-full padding-bottom-2"> <li class="flex-1 width-full height-full padding-bottom-2">
<div class="usa-card__container border-0"> <div class="usa-card__container border-0">
<ol start="7" class="best-practices-list set-two"> <ol start="7" class="guides-list set-two">
<li>Identify yourself in the text message. Use a consistent and familiar <b>program name</b> to precede each <li>Identify yourself in the text message. Use a consistent and familiar <b>program name</b> to precede each
text you send.</li> text you send.</li>
<li>Personalize with <b>first name</b>. Through A/B testing, Code for America saw an increase in <li>Personalize with <b>first name</b>. Through A/B testing, Code for America saw an increase in
@@ -98,7 +101,7 @@
<p class="sms-message-wrapper text-left"> <p class="sms-message-wrapper text-left">
{{circle_number(7) }}<b>Dept. of Social Services:</b> Hi {{circle_number(8) }}<b>Julie,</b> Your Medicaid {{circle_number(7) }}<b>Dept. of Social Services:</b> Hi {{circle_number(8) }}<b>Julie,</b> Your Medicaid
renewal is closing December 31, 2023. You can renew online at {{circle_number(9) }}<a renewal is closing December 31, 2023. You can renew online at {{circle_number(9) }}<a
href="https://www.application.yourstate.gov" target="_blank" class="use-link usa-link--external" href="https://www.application.yourstate.gov" target="_blank"
rel="application.yourstate.gov">https://www.application.yourstate.gov</a> or {{circle_number(10) }} rel="application.yourstate.gov">https://www.application.yourstate.gov</a> or {{circle_number(10) }}
<b>call the number on the back</b> of your Medicaid card. <b>call the number on the back</b> of your Medicaid card.
</p> </p>
@@ -114,14 +117,14 @@
<p>If you're sending one-way notifications, phone carriers allow a single auto-response message that will be <p>If you're sending one-way notifications, phone carriers allow a single auto-response message that will be
generated if a recipient tries to text a response to your message. Use the auto-response to reaffirm your key generated if a recipient tries to text a response to your message. Use the auto-response to reaffirm your key
messages around legitimacy and communicate to recipients that texts are coming from an automated system.</p> messages around legitimacy and communicate to recipients that texts are coming from an automated system.</p>
<ol class="best-practices-list set-three"> <ol class="guides-list set-three">
<li>Provide <b>a way to contact a human</b> in any auto-response text</li> <li>Provide <b>a way to contact a human</b> in any auto-response text</li>
<li>Provide <b>information on how to opt out</b> and opt back in</li> <li>Provide <b>information on how to opt out</b> and opt back in</li>
</ol> </ol>
</div> </div>
</li> </li>
<li class="usa-card flex-1 usa-card--media-right width-full padding-top-3"> <li class="usa-card flex-1 usa-card--media-right width-full padding-top-3">
<div class="usa-card__container border-0 width-full overflow-hidden best-practices"> <div class="usa-card__container border-0 width-full overflow-hidden guides">
<img class="width-full" src="{{ asset_url('images/phone_grey.svg') }}" role="img" alt="Phone" /> <img class="width-full" src="{{ asset_url('images/phone_grey.svg') }}" role="img" alt="Phone" />
<div class="position-absolute flex text-center padding-5 padding-top-15"> <div class="position-absolute flex text-center padding-5 padding-top-15">
<p class="sms-message-wrapper text-left"> <p class="sms-message-wrapper text-left">
@@ -167,7 +170,7 @@
}, },
] %} ] %}
{% with card_contents=card_contents %}{% include "components/best-practices/cards.html" %}{% {% with card_contents=card_contents %}{% include "components/guides/cards.html" %}{%
endwith %} endwith %}
<h3 class="padding-bottom-2">Prepare your team</h3> <h3 class="padding-bottom-2">Prepare your team</h3>
{% set card_contents = [ {% set card_contents = [
@@ -187,7 +190,7 @@
pages or within case management notes.", pages or within case management notes.",
}, },
] %} ] %}
{% with card_contents=card_contents %}{% include "components/best-practices/cards.html" %}{% {% with card_contents=card_contents %}{% include "components/guides/cards.html" %}{%
endwith %} endwith %}
</section> </section>
{% endblock %} {% endblock %}
@@ -1,4 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% set page_title = "Text in multiple languages" %} {% set page_title = "Text in multiple languages" %}
@@ -7,7 +8,8 @@
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} {{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p class="font-sans-lg text-base"> What to know as you plan translated texts.</p> <p class="font-sans-lg text-base"> What to know as you plan translated texts.</p>
@@ -1,4 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% set page_title = "Rules and regulations" %} {% set page_title = "Rules and regulations" %}
@@ -7,7 +8,8 @@
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} {{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p class="font-sans-lg text-base">Understand what is required when texting the public.</p> <p class="font-sans-lg text-base">Understand what is required when texting the public.</p>
@@ -20,7 +22,7 @@
If you do need expressed consent, consider including a pre-checked plain language opt-in (i.e. “Its OK to text If you do need expressed consent, consider including a pre-checked plain language opt-in (i.e. “Its OK to text
me.”) on me.”) on
digital forms. Be sure to ask for an up-to-date phone number and include a question about the recipients preferred digital forms. Be sure to ask for an up-to-date phone number and include a question about the recipients preferred
language for text messages if you expect to <a href="../best-practices/multiple-languages">translate your text language for text messages if you expect to <a href="../guides/multiple-languages">translate your text
messages</a> in messages</a> in
languages other than English. languages other than English.
</p> </p>
@@ -79,7 +81,7 @@
<h3>Opting out</h3> <h3>Opting out</h3>
<p> <p>
There is no policy requirement for senders to communicate opt-out options, but <a There is no policy requirement for senders to communicate opt-out options, but <a
href="../best-practices/establish-trust#as-people-receive-texts"> including instructions in introductory and/or href="../guides/establish-trust#as-people-receive-texts"> including instructions in introductory and/or
auto-response texts </a> on how to opt out and opt back in are effective ways to establish trust with your auto-response texts </a> on how to opt out and opt back in are effective ways to establish trust with your
audience. audience.
</p> </p>
@@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% from "components/best-practices/circle_number.html" import circle_number %} {% import "components/nav_breadcrumb.html" as breadcrumbs %}
{% from "components/guides/circle_number.html" import circle_number %}
{% set page_title = "Write texts that provoke action" %} {% set page_title = "Write texts that provoke action" %}
@@ -8,7 +9,8 @@
{% endblock %} {% endblock %}
{% block content_column_content %} {% block content_column_content %}
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} {{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
<section class="usa-prose"> <section class="usa-prose">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p class="font-sans-lg text-base"> Help your audience know what to do with the information you send.</p> <p class="font-sans-lg text-base"> Help your audience know what to do with the information you send.</p>
@@ -40,11 +42,11 @@
<li>Use a neutral, direct, and professional tone. This works better than a friendly or overly casual tone.</li> <li>Use a neutral, direct, and professional tone. This works better than a friendly or overly casual tone.</li>
</ul> </ul>
<h2>Build conditions for action</h2> <h2>Build conditions for action</h2>
<ul class="usa-card-group flex-1 flex-wrap padding-top-2 best-practices-flex-container"> <ul class="usa-card-group flex-1 flex-wrap padding-top-2 guides-flex-container">
<li class="flex-1 width-full height-full padding-bottom-2"> <li class="flex-1 width-full height-full padding-bottom-2">
<div class="usa-card__container border-0"> <div class="usa-card__container border-0">
<p>For example, getting a person to update their mailing address:</p> <p>For example, getting a person to update their mailing address:</p>
<ol class="best-practices-list"> <ol class="guides-list">
<li>Clearly state the information and the response you want the recipient to take.</li> <li>Clearly state the information and the response you want the recipient to take.</li>
<li>Point directly to where the action can be completed, not to more information.</li> <li>Point directly to where the action can be completed, not to more information.</li>
<li>Make sure the action can be completed via mobile phone, like calling a person or going to a <li>Make sure the action can be completed via mobile phone, like calling a person or going to a
@@ -78,7 +80,8 @@
</li> </li>
</ul> </ul>
<h2>What provoking action looks like</h2> <h2>What provoking action looks like</h2>
<p class="padding-bottom-2"><a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10002044/" target="_blank">Evidence <p class="padding-bottom-2"><a class="use-link usa-link--external"
href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10002044/" target="_blank">Evidence
shows</a> that employing shows</a> that employing
behavioral science is an effective way to increase the behavioral science is an effective way to increase the
likelihood of a recipient likelihood of a recipient
@@ -100,7 +103,7 @@
internet services <b>that belong to you</b>.", internet services <b>that belong to you</b>.",
}, },
] %} ] %}
{% with card_contents=card_contents, text_align='left' %}{% include "components/best-practices/cards.html" %}{% {% with card_contents=card_contents, text_align='left' %}{% include "components/guides/cards.html" %}{%
endwith %} endwith %}
</section> </section>
{% endblock %} {% endblock %}
+4
View File
@@ -103,6 +103,7 @@ def generate_notifications_csv(**kwargs):
"Carrier Response", "Carrier Response",
"Status", "Status",
"Time", "Time",
"Carrier",
] ]
for header in original_column_headers: for header in original_column_headers:
if header.lower() != "phone number": if header.lower() != "phone number":
@@ -118,6 +119,7 @@ def generate_notifications_csv(**kwargs):
"Carrier Response", "Carrier Response",
"Status", "Status",
"Time", "Time",
"Carrier",
] ]
yield ",".join(fieldnames) + "\n" yield ",".join(fieldnames) + "\n"
@@ -140,6 +142,7 @@ def generate_notifications_csv(**kwargs):
notification["provider_response"], notification["provider_response"],
notification["status"], notification["status"],
preferred_tz_created_at, preferred_tz_created_at,
notification["carrier"],
] ]
for header in original_column_headers: for header in original_column_headers:
if header.lower() != "phone number": if header.lower() != "phone number":
@@ -158,6 +161,7 @@ def generate_notifications_csv(**kwargs):
notification["provider_response"], notification["provider_response"],
notification["status"], notification["status"],
preferred_tz_created_at, preferred_tz_created_at,
notification["carrier"],
] ]
yield Spreadsheet.from_rows([map(str, values)]).as_csv_data yield Spreadsheet.from_rows([map(str, values)]).as_csv_data
+1 -1
View File
@@ -1,6 +1,6 @@
env: production env: production
instances: 2 instances: 2
memory: 1.5G memory: 2G
command: newrelic-admin run-program gunicorn -c /home/vcap/app/gunicorn_config.py application command: newrelic-admin run-program gunicorn -c /home/vcap/app/gunicorn_config.py application
public_admin_route: beta.notify.gov public_admin_route: beta.notify.gov
cloud_dot_gov_route: notify.app.cloud.gov cloud_dot_gov_route: notify.app.cloud.gov
+244 -178
View File
@@ -12,7 +12,7 @@
"@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/stream": "^3.0.1", "@rollup/stream": "^3.0.1",
"@uswds/uswds": "^3.9.0", "@uswds/uswds": "^3.10.0",
"cbor-js": "0.1.0", "cbor-js": "0.1.0",
"d3": "^7.9.0", "d3": "^7.9.0",
"govuk_frontend_toolkit": "^9.0.1", "govuk_frontend_toolkit": "^9.0.1",
@@ -21,10 +21,10 @@
"hogan": "1.0.2", "hogan": "1.0.2",
"jquery": "3.7.1", "jquery": "3.7.1",
"morphdom": "^2.7.4", "morphdom": "^2.7.4",
"playwright": "^1.48.2", "playwright": "^1.49.0",
"python": "^0.0.4", "python": "^0.0.4",
"query-command-supported": "1.0.0", "query-command-supported": "1.0.0",
"sass-embedded": "^1.80.6", "sass-embedded": "^1.82.0",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"timeago": "1.6.7", "timeago": "1.6.7",
"vinyl-buffer": "^1.0.1", "vinyl-buffer": "^1.0.1",
@@ -50,7 +50,7 @@
"jest-environment-jsdom": "^29.2.2", "jest-environment-jsdom": "^29.2.2",
"jshint": "2.13.6", "jshint": "2.13.6",
"jshint-stylish": "2.2.1", "jshint-stylish": "2.2.1",
"rollup": "^4.24.4", "rollup": "^4.28.0",
"rollup-plugin-commonjs": "10.1.0", "rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-node-resolve": "5.2.0" "rollup-plugin-node-resolve": "5.2.0"
}, },
@@ -2667,216 +2667,234 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz",
"integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", "integrity": "sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz",
"integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", "integrity": "sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz",
"integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", "integrity": "sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz",
"integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", "integrity": "sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz",
"integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", "integrity": "sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz",
"integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", "integrity": "sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz",
"integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", "integrity": "sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz",
"integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", "integrity": "sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz",
"integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", "integrity": "sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz",
"integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", "integrity": "sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz",
"integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", "integrity": "sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz",
"integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", "integrity": "sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz",
"integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", "integrity": "sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz",
"integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", "integrity": "sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz",
"integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", "integrity": "sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz",
"integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", "integrity": "sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz",
"integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", "integrity": "sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz",
"integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", "integrity": "sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -3485,11 +3503,10 @@
} }
}, },
"node_modules/@uswds/uswds": { "node_modules/@uswds/uswds": {
"version": "3.9.0", "version": "3.10.0",
"resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.9.0.tgz", "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.10.0.tgz",
"integrity": "sha512-8THm36j7iLjrDiI1D0C6b3hHsmM/Sy5Iiz+IjE+i/gYzVUMG9XVthxAZYonhU97Q1b079n6nYwlUmDSYowJecQ==", "integrity": "sha512-LWFTQzp4e3kqtnD/Wsyfx9uGTkn5GEpzhscNWJMIsdWBGKtiu96QT99oRJUmcsB6HbGhR0Th0FtlK/Zzx2WghA==",
"dependencies": { "dependencies": {
"object-assign": "4.1.1",
"receptor": "1.0.0", "receptor": "1.0.0",
"resolve-id-refs": "0.1.0" "resolve-id-refs": "0.1.0"
}, },
@@ -5146,10 +5163,11 @@
} }
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
"shebang-command": "^2.0.0", "shebang-command": "^2.0.0",
@@ -8314,7 +8332,8 @@
"node_modules/immutable": { "node_modules/immutable": {
"version": "4.3.6", "version": "4.3.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==" "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==",
"dev": true
}, },
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
@@ -12011,11 +12030,11 @@
} }
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.48.2", "version": "1.49.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz",
"integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", "integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==",
"dependencies": { "dependencies": {
"playwright-core": "1.48.2" "playwright-core": "1.49.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -12028,9 +12047,9 @@
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.48.2", "version": "1.49.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz",
"integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", "integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==",
"bin": { "bin": {
"playwright-core": "cli.js" "playwright-core": "cli.js"
}, },
@@ -12951,9 +12970,10 @@
"license": "Unlicense" "license": "Unlicense"
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.24.4", "version": "4.28.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.0.tgz",
"integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", "integrity": "sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@types/estree": "1.0.6" "@types/estree": "1.0.6"
}, },
@@ -12965,24 +12985,24 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.24.4", "@rollup/rollup-android-arm-eabi": "4.28.0",
"@rollup/rollup-android-arm64": "4.24.4", "@rollup/rollup-android-arm64": "4.28.0",
"@rollup/rollup-darwin-arm64": "4.24.4", "@rollup/rollup-darwin-arm64": "4.28.0",
"@rollup/rollup-darwin-x64": "4.24.4", "@rollup/rollup-darwin-x64": "4.28.0",
"@rollup/rollup-freebsd-arm64": "4.24.4", "@rollup/rollup-freebsd-arm64": "4.28.0",
"@rollup/rollup-freebsd-x64": "4.24.4", "@rollup/rollup-freebsd-x64": "4.28.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.24.4", "@rollup/rollup-linux-arm-gnueabihf": "4.28.0",
"@rollup/rollup-linux-arm-musleabihf": "4.24.4", "@rollup/rollup-linux-arm-musleabihf": "4.28.0",
"@rollup/rollup-linux-arm64-gnu": "4.24.4", "@rollup/rollup-linux-arm64-gnu": "4.28.0",
"@rollup/rollup-linux-arm64-musl": "4.24.4", "@rollup/rollup-linux-arm64-musl": "4.28.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", "@rollup/rollup-linux-powerpc64le-gnu": "4.28.0",
"@rollup/rollup-linux-riscv64-gnu": "4.24.4", "@rollup/rollup-linux-riscv64-gnu": "4.28.0",
"@rollup/rollup-linux-s390x-gnu": "4.24.4", "@rollup/rollup-linux-s390x-gnu": "4.28.0",
"@rollup/rollup-linux-x64-gnu": "4.24.4", "@rollup/rollup-linux-x64-gnu": "4.28.0",
"@rollup/rollup-linux-x64-musl": "4.24.4", "@rollup/rollup-linux-x64-musl": "4.28.0",
"@rollup/rollup-win32-arm64-msvc": "4.24.4", "@rollup/rollup-win32-arm64-msvc": "4.28.0",
"@rollup/rollup-win32-ia32-msvc": "4.24.4", "@rollup/rollup-win32-ia32-msvc": "4.28.0",
"@rollup/rollup-win32-x64-msvc": "4.24.4", "@rollup/rollup-win32-x64-msvc": "4.28.0",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -13091,16 +13111,18 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/sass-embedded": { "node_modules/sass-embedded": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.82.0.tgz",
"integrity": "sha512-Og4aqBnaA3oJfIpHaLuNATAqzBRgUJDYJy2X15V59cot2wYOtiT/ciPnyuq1o7vpDEeOkHhEd+mSviSlXoETug==", "integrity": "sha512-v13sRVVZtWAQLpAGTz5D8hy+oyNKRHao5tKVc/P6AMqSP+jDM8X6GkEpL0jfbu3MaN2/hAQsd4Qx14GG1u0prQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@bufbuild/protobuf": "^2.0.0", "@bufbuild/protobuf": "^2.0.0",
"buffer-builder": "^0.2.0", "buffer-builder": "^0.2.0",
"colorjs.io": "^0.5.0", "colorjs.io": "^0.5.0",
"immutable": "^4.0.0", "immutable": "^5.0.2",
"rxjs": "^7.4.0", "rxjs": "^7.4.0",
"supports-color": "^8.1.1", "supports-color": "^8.1.1",
"sync-child-process": "^1.0.2",
"varint": "^6.0.0" "varint": "^6.0.0"
}, },
"bin": { "bin": {
@@ -13110,35 +13132,36 @@
"node": ">=16.0.0" "node": ">=16.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"sass-embedded-android-arm": "1.80.6", "sass-embedded-android-arm": "1.82.0",
"sass-embedded-android-arm64": "1.80.6", "sass-embedded-android-arm64": "1.82.0",
"sass-embedded-android-ia32": "1.80.6", "sass-embedded-android-ia32": "1.82.0",
"sass-embedded-android-riscv64": "1.80.6", "sass-embedded-android-riscv64": "1.82.0",
"sass-embedded-android-x64": "1.80.6", "sass-embedded-android-x64": "1.82.0",
"sass-embedded-darwin-arm64": "1.80.6", "sass-embedded-darwin-arm64": "1.82.0",
"sass-embedded-darwin-x64": "1.80.6", "sass-embedded-darwin-x64": "1.82.0",
"sass-embedded-linux-arm": "1.80.6", "sass-embedded-linux-arm": "1.82.0",
"sass-embedded-linux-arm64": "1.80.6", "sass-embedded-linux-arm64": "1.82.0",
"sass-embedded-linux-ia32": "1.80.6", "sass-embedded-linux-ia32": "1.82.0",
"sass-embedded-linux-musl-arm": "1.80.6", "sass-embedded-linux-musl-arm": "1.82.0",
"sass-embedded-linux-musl-arm64": "1.80.6", "sass-embedded-linux-musl-arm64": "1.82.0",
"sass-embedded-linux-musl-ia32": "1.80.6", "sass-embedded-linux-musl-ia32": "1.82.0",
"sass-embedded-linux-musl-riscv64": "1.80.6", "sass-embedded-linux-musl-riscv64": "1.82.0",
"sass-embedded-linux-musl-x64": "1.80.6", "sass-embedded-linux-musl-x64": "1.82.0",
"sass-embedded-linux-riscv64": "1.80.6", "sass-embedded-linux-riscv64": "1.82.0",
"sass-embedded-linux-x64": "1.80.6", "sass-embedded-linux-x64": "1.82.0",
"sass-embedded-win32-arm64": "1.80.6", "sass-embedded-win32-arm64": "1.82.0",
"sass-embedded-win32-ia32": "1.80.6", "sass-embedded-win32-ia32": "1.82.0",
"sass-embedded-win32-x64": "1.80.6" "sass-embedded-win32-x64": "1.82.0"
} }
}, },
"node_modules/sass-embedded-android-arm": { "node_modules/sass-embedded-android-arm": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.82.0.tgz",
"integrity": "sha512-UeUKMTRsnz4/dh7IzvhjONxa4/jmVp539CHDd8VZOsqg9M3HcNJNIkUzQWbuwZ+nSlWrTuo7Tvn3XlypopCBzw==", "integrity": "sha512-ttGMvWnA/5TYdZTjr5fWHDbb9nZgKipHKCc9zZQRF5HjUydOYWKNqmAJHQtbFWaq35kd5qn6yiE73IJN6eJ6wA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -13148,12 +13171,13 @@
} }
}, },
"node_modules/sass-embedded-android-arm64": { "node_modules/sass-embedded-android-arm64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.82.0.tgz",
"integrity": "sha512-4rC4ZGM/k4ENVjLXnK3JTst8e8FI9MHSol2Fl7dCdYyJ3KLnlt4qL4AEYfU8zq1tcBb7CBOSZVR+CzCKubnXdg==", "integrity": "sha512-bldHMs02QQWXsgHUZRgolNnZdMjN6XHvmUYoRkzmFq7lsvtLU6SJg2S1Wa9IZJs9jRWdTmOgA6YibSf3pROyFQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -13163,12 +13187,13 @@
} }
}, },
"node_modules/sass-embedded-android-ia32": { "node_modules/sass-embedded-android-ia32": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.82.0.tgz",
"integrity": "sha512-Lxz2SXE2KdHnynuHF+D6flDvrd55/zaEAWUeka9MxEr6FmR66d8UBOIy5ETwCSUd//S/SE5Jl6oTnHppgD1zNA==", "integrity": "sha512-FUJOnxw8IYKuYuxxiOkk6QXle8/yQFtKjnuSAJuZ5ZpLVMcSZzLc3SWOtuEXYx5iSAfJCO075o2ZoG/pPrJ9aw==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -13178,12 +13203,13 @@
} }
}, },
"node_modules/sass-embedded-android-riscv64": { "node_modules/sass-embedded-android-riscv64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.82.0.tgz",
"integrity": "sha512-hKdxY/oOqB+JJhSoBTDM5DJO1j/xtxQgayh2cLCCUx37IQQe3SEdc3V2JFf/4mIo5peaS4cjqwwSATF+l2zaXg==", "integrity": "sha512-rd+vc+sxJxNnbhaubiIJmnb1b3FvC9wxCIq8spstopbO7o1uufvBBDeRoFSJaN+7oNhamzjlYGdu6aQoQNs3+A==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -13193,12 +13219,13 @@
} }
}, },
"node_modules/sass-embedded-android-x64": { "node_modules/sass-embedded-android-x64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.82.0.tgz",
"integrity": "sha512-Eap2Fi3kTx/rVLBsOnOp5RYPr5+lFjTZ652zR24dmYFe9/sDgasakJIOPjOvD2bRuL9z0uWEY1AXVeeOPeZKrg==", "integrity": "sha512-EVlybGTgJ8wNLyWj8RUatPXSnmIcvCsx3EfsRfBfhGihLbn4NNpavYO9QsvZzI2XWbJqHLBCd+CvkTcDw/TaSQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -13208,12 +13235,13 @@
} }
}, },
"node_modules/sass-embedded-darwin-arm64": { "node_modules/sass-embedded-darwin-arm64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.82.0.tgz",
"integrity": "sha512-0mnAx8Vq6Gxj3PQt3imgITfK33hhqrSKpyHSuab71gZZni5opsdtoggq2JawW+1taRFTEZwbZJLKZ0MBDbwCCA==", "integrity": "sha512-LvdJPojjKlNGYOB0nSUR/ZtMDuAF4puspHlwK42aA/qK292bfSkMUKZPPapB2aSRwccc/ieBq5fI7n/WHrOCVw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -13223,12 +13251,13 @@
} }
}, },
"node_modules/sass-embedded-darwin-x64": { "node_modules/sass-embedded-darwin-x64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.82.0.tgz",
"integrity": "sha512-Ib20yNZFOrJ7YVT+ltoe+JQNKPcRclM3iLAK69XZZYcSeFM/72SCoQBAaVGIpT23dxDp7FXiE4lO602c3xTRwQ==", "integrity": "sha512-6LfnD6YmG1aBfd3ReqMOJDb6Pg2Z/hmlJB7nU+Lb3E+hCNjAZAgeUHQxU/Pm1eIqJJTU/h4ib5QP0Pt9O8yVnw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -13238,12 +13267,13 @@
} }
}, },
"node_modules/sass-embedded-linux-arm": { "node_modules/sass-embedded-linux-arm": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.82.0.tgz",
"integrity": "sha512-QR0Q6TZox/ThuU2r9c0s3fKCgU2rXAEocpitdgxFp6tta+GsQlMFV3oON2unAa8Bwnuxkmf0YOaK0Oy/TwzkXw==", "integrity": "sha512-ozjdC5rWzyi5Vo300I4tVZzneXOTQUiaxOr7DjtN26HuFaGAGCGmvThh2BRV4RvySg++5H9rdFu+VgyUQ5iukw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13253,12 +13283,13 @@
} }
}, },
"node_modules/sass-embedded-linux-arm64": { "node_modules/sass-embedded-linux-arm64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.82.0.tgz",
"integrity": "sha512-n5r98pBXawrQQKaxIYCMM1zDpnngsqxTkOrmvsYLFiAMCSbR0lWf/7sBB33k/Pm0D6dsbp3jpHilCoQNKI3jIw==", "integrity": "sha512-590/y0HJr/JiyxaqgR7Xf9P20BIhJ+zhB/afAnVuZe/4lEfCpTyM5xMe2+sKLsqtrVyzs9Zm/M4S4ASUOPCggA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13268,12 +13299,13 @@
} }
}, },
"node_modules/sass-embedded-linux-ia32": { "node_modules/sass-embedded-linux-ia32": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.82.0.tgz",
"integrity": "sha512-O6dWZdcOkryRdDCxVMGOeVowgblpDgVcAuRtZ1F1X7XfbpDriTQm64D+9vVZIrywYSPoJfQMJJ662cr0wUs9IQ==", "integrity": "sha512-hpc4acZ3UTjjJ3Q/GUXqQOCSml6AFKaku0HMawra9bKyRmOpxn8V5hqgXeOWVjK2oQzCmCnJvwKoQUP+S/SIYQ==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13283,12 +13315,13 @@
} }
}, },
"node_modules/sass-embedded-linux-musl-arm": { "node_modules/sass-embedded-linux-musl-arm": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.82.0.tgz",
"integrity": "sha512-X9FC8s8fvQGRiXc+eATlZ57N44Iq3nNa0M0ugi3ysdJwkaNYvOeS4QzBHKQAaw3QiTqdxTnLUHHVBkyzdCi9pw==", "integrity": "sha512-R5PQmY/I+GSoMtfLo8GgHkvF/q6x6y8VNM7yu/Ac1mJj86n48VFi29W1HfY2496+Q6cpAq7toobDj7YfldIdVA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13298,12 +13331,13 @@
} }
}, },
"node_modules/sass-embedded-linux-musl-arm64": { "node_modules/sass-embedded-linux-musl-arm64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.82.0.tgz",
"integrity": "sha512-VeUSHUi3MAsvOlg9QI4X/2j04h1659aE+7qKP/282CYBTrGkjFGSXZhIki9WKWDgIpDiSInRYXfQQRWhPhjCDg==", "integrity": "sha512-bc2MUSMv/jabnNGEyKP2jQAYZoEzTT/c633W6QoeSEWETGCuTNjaHvWWE6qSI6/UfRg1EpuV1LQA2jPMzZfv/w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13313,12 +13347,13 @@
} }
}, },
"node_modules/sass-embedded-linux-musl-ia32": { "node_modules/sass-embedded-linux-musl-ia32": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.82.0.tgz",
"integrity": "sha512-GqitS2Nab8ah0+wfCqaxW1hnI1piC08FimL6+lM9YWK5DbCOOF82IapbvJOy0feUmd/wNnHmyNTgE9h0zVMFdQ==", "integrity": "sha512-ZQKCFKm5TBcJ19UG6uUQmIKfVCJIWMb7e1a93lGeujSb9gyKF5Fb6MN3tuExoT7iFK8zU0Z9iyHqh93F58lcCw==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13328,12 +13363,13 @@
} }
}, },
"node_modules/sass-embedded-linux-musl-riscv64": { "node_modules/sass-embedded-linux-musl-riscv64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.82.0.tgz",
"integrity": "sha512-ySs15z7QSRRQK/aByEEqaJLYW/sTpfynefNPZCtsVNVEzNRwy+DRpxNChtxo+QjKq97ocXETbdG5KLik7QOTJg==", "integrity": "sha512-5meSU8BHFeaT09RWfkuUrikRlC+WZcYb9To7MpfV1d9nlD7CZ2xydPExK+mj3DqRuQvTbvhMPcr7f+pHlgHINQ==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13343,12 +13379,13 @@
} }
}, },
"node_modules/sass-embedded-linux-musl-x64": { "node_modules/sass-embedded-linux-musl-x64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.82.0.tgz",
"integrity": "sha512-DzeNqU/SN0mWFznoOH4RtVGcrg3Eoa41pUQhKMtrhNbCmIE1zNDunUiAEVTNpdHJF4nxf7ELUPXWmStM31CbUQ==", "integrity": "sha512-ASLAMfjWv7YEPBvEOVlb3zzHq8l4Y9Eh4x3m7B1dNauGVbO11Yng5cPCX/XbwGVf30BtE75pwqvV7oXxBtN15w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13358,12 +13395,13 @@
} }
}, },
"node_modules/sass-embedded-linux-riscv64": { "node_modules/sass-embedded-linux-riscv64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.82.0.tgz",
"integrity": "sha512-AyoHJ3icV9xuJjq1YzJqpEj2XfiC/KBkVYTUrCELKiXP0DN1gi/BpUwZNCAgCM3CyEdMef4LQM/ztCYJxYzdyg==", "integrity": "sha512-qWvRDXCXH3GzD8OcP0ntd8gBTK3kZyUeyXmxQDZyEtMAM4STC2Tn7+5+2JYYHlppzqWnZPFBNESvpKeOtHaBBw==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13373,12 +13411,13 @@
} }
}, },
"node_modules/sass-embedded-linux-x64": { "node_modules/sass-embedded-linux-x64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.82.0.tgz",
"integrity": "sha512-EohsE9CEqx0ycylnsEj/0DNPG99Tb0qAVZspiAs5xHFCJjXOFfp3cRQu0BRf+lZ1b72IhPFXymzVtojvzUHb7g==", "integrity": "sha512-AmRaHqShztwfep+M4NagdGaY7fTyWGSOM3k4Z/dd7q4nZclXbALLqNJtKx8xOM7A41LHYJ9zDpIBVRkrh0PzTA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -13388,12 +13427,13 @@
} }
}, },
"node_modules/sass-embedded-win32-arm64": { "node_modules/sass-embedded-win32-arm64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.82.0.tgz",
"integrity": "sha512-29wETQi1ykeVvpd4zMVokpQKFSOZskGJzZawuuNCdo7BHjHKIRDsqbz8YT1CewHPBshI0hfD21fenmjxYjGXPQ==", "integrity": "sha512-zL9JDQZHXHSGAZe5DqSrR86wMHbm9QPziU4/3hoIG+99StuS74CuV42+hw/+FXXBkXMWbjKWsyF/HZt+I/wJuw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -13403,12 +13443,13 @@
} }
}, },
"node_modules/sass-embedded-win32-ia32": { "node_modules/sass-embedded-win32-ia32": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.82.0.tgz",
"integrity": "sha512-1s3OpK2iTIfIL/a91QhAQnffsbuWfnsM8Lx4Fxt0f7ErnxjCV6q8MUFTV/UhcLtLyTFnPCA62DLjp2KGCjMI9A==", "integrity": "sha512-xE+AzLquCkFPnnpo0NHjQdLRIhG1bVs42xIKx42aUbVLYKkBDvbBGpw6EtTscRMyvcjoOqGH5saRvSFComUQcw==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -13418,12 +13459,13 @@
} }
}, },
"node_modules/sass-embedded-win32-x64": { "node_modules/sass-embedded-win32-x64": {
"version": "1.80.6", "version": "1.82.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.80.6.tgz", "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.82.0.tgz",
"integrity": "sha512-0pH4Zr9silHkcmLPC0ghnD3DI0vMsjA7dKvGR32/RbbjOSvHV5cDQRLiuVJAPp34dfMA7kJd1ysSchRdH0igAQ==", "integrity": "sha512-cEgfOQG5womOzzk16ReTv2dxPq5BG16LgLUold/LH9IZH86u4E/MN7Fspf4RWeEJ2EcLdew9QYSC2YWs1l98dQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -13445,6 +13487,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/sass-embedded/node_modules/immutable": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz",
"integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw=="
},
"node_modules/sass-embedded/node_modules/supports-color": { "node_modules/sass-embedded/node_modules/supports-color": {
"version": "8.1.1", "version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
@@ -13994,6 +14041,25 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true "dev": true
}, },
"node_modules/sync-child-process": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz",
"integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==",
"dependencies": {
"sync-message-port": "^1.0.0"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/sync-message-port": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz",
"integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/table": { "node_modules/table": {
"version": "6.8.2", "version": "6.8.2",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz",
+4 -4
View File
@@ -28,7 +28,7 @@
"@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/stream": "^3.0.1", "@rollup/stream": "^3.0.1",
"@uswds/uswds": "^3.9.0", "@uswds/uswds": "^3.10.0",
"cbor-js": "0.1.0", "cbor-js": "0.1.0",
"d3": "^7.9.0", "d3": "^7.9.0",
"govuk_frontend_toolkit": "^9.0.1", "govuk_frontend_toolkit": "^9.0.1",
@@ -37,10 +37,10 @@
"hogan": "1.0.2", "hogan": "1.0.2",
"jquery": "3.7.1", "jquery": "3.7.1",
"morphdom": "^2.7.4", "morphdom": "^2.7.4",
"playwright": "^1.48.2", "playwright": "^1.49.0",
"python": "^0.0.4", "python": "^0.0.4",
"query-command-supported": "1.0.0", "query-command-supported": "1.0.0",
"sass-embedded": "^1.80.6", "sass-embedded": "^1.82.0",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"timeago": "1.6.7", "timeago": "1.6.7",
"vinyl-buffer": "^1.0.1", "vinyl-buffer": "^1.0.1",
@@ -66,7 +66,7 @@
"jest-environment-jsdom": "^29.2.2", "jest-environment-jsdom": "^29.2.2",
"jshint": "2.13.6", "jshint": "2.13.6",
"jshint-stylish": "2.2.1", "jshint-stylish": "2.2.1",
"rollup": "^4.24.4", "rollup": "^4.28.0",
"rollup-plugin-commonjs": "10.1.0", "rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-node-resolve": "5.2.0" "rollup-plugin-node-resolve": "5.2.0"
} }
Generated
+5 -5
View File
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]] [[package]]
name = "ago" name = "ago"
@@ -1616,18 +1616,18 @@ files = [
[[package]] [[package]]
name = "moto" name = "moto"
version = "5.0.18" version = "5.0.22"
description = "" description = ""
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "moto-5.0.18-py2.py3-none-any.whl", hash = "sha256:8e25401f7d7910e19a732b417e0d503ef86cf4de9114a273dd62679a42f3be1c"}, {file = "moto-5.0.22-py3-none-any.whl", hash = "sha256:defae32e834ba5674f77cbbe996b41dc248dd81289af8032fa3e847284409b29"},
{file = "moto-5.0.18.tar.gz", hash = "sha256:8a7ad2f53a2e6cc9db2ff65c0e0d4b5d7e78bc00b825c9e1ff6cc394371e76e9"}, {file = "moto-5.0.22.tar.gz", hash = "sha256:daf47b8a1f5f190cd3eaa40018a643f38e542277900cf1db7f252cedbfed998f"},
] ]
[package.dependencies] [package.dependencies]
boto3 = ">=1.9.201" boto3 = ">=1.9.201"
botocore = ">=1.14.0" botocore = ">=1.14.0,<1.35.45 || >1.35.45,<1.35.46 || >1.35.46"
cryptography = ">=3.3.1" cryptography = ">=3.3.1"
Jinja2 = ">=2.10.1" Jinja2 = ">=2.10.1"
python-dateutil = ">=2.1,<3.0.0" python-dateutil = ">=2.1,<3.0.0"
+1
View File
@@ -125,6 +125,7 @@ def test_static_pages(client_request, mock_get_organization_by_domain, view, moc
"write_for_action", "write_for_action",
"multiple_languages", "multiple_languages",
"benchmark_performance", "benchmark_performance",
"guidance_index"
] ]
return ( return (
not current_app.config["FEATURE_BEST_PRACTICES_ENABLED"] not current_app.config["FEATURE_BEST_PRACTICES_ENABLED"]
+3
View File
@@ -18,6 +18,7 @@ EXCLUDED_ENDPOINTS = tuple(
Navigation.get_endpoint_with_blueprint, Navigation.get_endpoint_with_blueprint,
{ {
"about_notify", "about_notify",
"about_security",
"accept_invite", "accept_invite",
"accept_org_invite", "accept_org_invite",
"accessibility_statement", "accessibility_statement",
@@ -219,6 +220,7 @@ EXCLUDED_ENDPOINTS = tuple(
"suspend_service", "suspend_service",
"template_history", "template_history",
"template_usage", "template_usage",
"test_feature_flags",
"tour_step", "tour_step",
"trial_mode", "trial_mode",
"trial_mode_new", "trial_mode_new",
@@ -258,6 +260,7 @@ EXCLUDED_ENDPOINTS = tuple(
"view_template_version", "view_template_version",
"view_template_versions", "view_template_versions",
"who_its_for", "who_its_for",
"why_text_messaging",
"write_for_action", "write_for_action",
}, },
) )
+11 -4
View File
@@ -58,6 +58,7 @@ def _get_notifications_csv(
"to": recipient, "to": recipient,
"recipient": recipient, "recipient": recipient,
"client_reference": "ref 1234", "client_reference": "ref 1234",
"carrier": "AT&T Mobility",
} }
for i in range(rows) for i in range(rows)
], ],
@@ -88,15 +89,15 @@ def get_notifications_csv_mock(
( (
None, None,
[ [
"Phone Number,Template,Sent by,Batch File,Carrier Response,Status,Time\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\r\n", "8005555555,foo,,,Did not like it,Delivered,1943-04-19 08:00:00 AM US/Eastern,AT&T Mobility\r\n",
], ],
), ),
( (
"Anne Example", "Anne Example",
[ [
"Phone Number,Template,Sent by,Batch File,Carrier Response,Status,Time\n", "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\r\n", # noqa "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", "Carrier Response",
"Status", "Status",
"Time", "Time",
"Carrier",
], ],
[ [
"8005555555", "8005555555",
@@ -144,6 +146,7 @@ def test_generate_notifications_csv_without_job(
"Did not like it", "Did not like it",
"Delivered", "Delivered",
"1943-04-19 08:00:00 AM US/Eastern", "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", "Carrier Response",
"Status", "Status",
"Time", "Time",
"Carrier",
"a", "a",
"b", "b",
"c", "c",
@@ -171,6 +175,7 @@ def test_generate_notifications_csv_without_job(
"Did not like it", "Did not like it",
"Delivered", "Delivered",
"1943-04-19 08:00:00 AM US/Eastern", "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", "Carrier Response",
"Status", "Status",
"Time", "Time",
"Carrier",
"a", "a",
"b", "b",
"c", "c",
@@ -201,6 +207,7 @@ def test_generate_notifications_csv_without_job(
"Did not like it", "Did not like it",
"Delivered", "Delivered",
"1943-04-19 08:00:00 AM US/Eastern", "1943-04-19 08:00:00 AM US/Eastern",
"AT&T Mobility",
"🐜,🐜", "🐜,🐜",
"🐝,🐝", "🐝,🐝",
"🦀", "🦀",
@@ -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}")
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}")
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()
+7 -7
View File
@@ -8,29 +8,29 @@ const sublinks = [
{ label: 'Trial Mode', path: '/using-notify/trial-mode' }, { label: 'Trial Mode', path: '/using-notify/trial-mode' },
{ label: 'Pricing', path: '/using-notify/pricing' }, { label: 'Pricing', path: '/using-notify/pricing' },
{ label: 'Delivery Status', path: '/using-notify/delivery-status' }, { label: 'Delivery Status', path: '/using-notify/delivery-status' },
{ label: 'Guidance', path: '/using-notify/guidance' }, { label: 'Guidance', path: '/guides/using-notify/guidance' },
{ label: 'Features', path: '/features' }, { label: 'Features', path: '/features' },
{ label: 'Roadmap', path: '/features/roadmap' }, { label: 'Roadmap', path: '/features/roadmap' },
{ label: 'Security', path: '/features/security' }, { label: 'Security', path: '/features/security' },
{ label: 'Support', path: '/support' }, { label: 'Support', path: '/support' },
{ label: 'Best Practices', path: '/guides/best-practices' }, { label: 'Best Practices', path: '/guides/best-practices' },
{ label: 'Clear Goals', path: '/guides/best-practices/clear-goals' }, { label: 'Clear Goals', path: '/guides/clear-goals' },
{ {
label: 'Rules And Regulations', label: 'Rules And Regulations',
path: '/guides/best-practices/rules-and-regulations', path: '/guides/rules-and-regulations',
}, },
{ label: 'Establish Trust', path: '/guides/best-practices/establish-trust' }, { label: 'Establish Trust', path: '/guides/establish-trust' },
{ {
label: 'Write For Action', label: 'Write For Action',
path: '/guides/best-practices/write-for-action', path: '/guides/write-for-action',
}, },
{ {
label: 'Multiple Languages', label: 'Multiple Languages',
path: '/guides/best-practices/multiple-languages', path: '/guides/multiple-languages',
}, },
{ {
label: 'Benchmark Performance', label: 'Benchmark Performance',
path: '/guides/best-practices/benchmark-performance', path: '/guides/benchmark-performance',
}, },
// Add more links here as needed // Add more links here as needed
]; ];