diff --git a/.ds.baseline b/.ds.baseline index 0aff1ada14..c64d226275 100644 --- a/.ds.baseline +++ b/.ds.baseline @@ -161,7 +161,7 @@ "filename": "app/config.py", "hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc", "is_verified": false, - "line_number": 121, + "line_number": 125, "is_secret": false } ], @@ -684,5 +684,5 @@ } ] }, - "generated_at": "2024-10-29T19:28:03Z" + "generated_at": "2024-11-14T15:53:44Z" } diff --git a/README.md b/README.md index e1a372fd32..95a07dbd31 100644 --- a/README.md +++ b/README.md @@ -372,15 +372,9 @@ After you have completed all setup steps, you will be unable to log in, because will not be a user in the database to link to the login.gov account you are using. So you will need to create that user in your database using the 'create-test-user' command. -Open two terminals pointing to the api project and then run these commands in the -respective terminals. +Open a terminal pointing to the api project and then run this command. -(Server 1) -env ALLOW_EXPIRED_API_TOKEN=1 make run-flask - -(Server 2) -poetry run flask command create-admin-jwt | tail -n 1 | pbcopy -poetry run flask command create-test-user --admin=True; +```poetry run flask command create-test-user --admin=True``` Supply your name, email address, mobile number, and password when prompted. Make sure the email address is the same one you are using in login.gov and make sure your phone number is in the format 5555555555. diff --git a/app/__init__.py b/app/__init__.py index 483d89ea06..64580fcc13 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -162,6 +162,17 @@ def _csp(config): def create_app(application): + application.config["FEATURE_BEST_PRACTICES_ENABLED"] = ( + os.getenv("FEATURE_BEST_PRACTICES_ENABLED", "false").lower() == "true" + ) + + @application.context_processor + def inject_feature_flags(): + feature_best_practices_enabled = application.config[ + "FEATURE_BEST_PRACTICES_ENABLED" + ] + return dict(FEATURE_BEST_PRACTICES_ENABLED=feature_best_practices_enabled) + notify_environment = os.environ["NOTIFY_ENVIRONMENT"] application.config.from_object(configs[notify_environment]) diff --git a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss index fe98aed09b..da5d77bf24 100644 --- a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss +++ b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss @@ -897,3 +897,22 @@ li.linked-card:hover svg, .usa-sidenav__item a { display: block; } + +.about-icon-list { + display: flex; + width: 24px; + height: 24px; + padding: 2px 1px; + justify-content: center; + align-items: center; + margin-right: 4px; +} + +.usa-icon-list__content{ + padding-left: 0; +} + +.indented-paragraph { + margin-left: calc(24px + 4px); + margin-top: 4px; +} diff --git a/app/config.py b/app/config.py index 249451c66f..f40b46dea3 100644 --- a/app/config.py +++ b/app/config.py @@ -91,6 +91,10 @@ class Config(object): getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true" ) + FEATURE_ABOUT_PAGE_ENABLED = ( + getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true" + ) + def _s3_credentials_from_env(bucket_prefix): return { diff --git a/app/main/views/index.py b/app/main/views/index.py index 28ede59d17..370a884015 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -2,7 +2,15 @@ import secrets from urllib.parse import unquote -from flask import abort, current_app, redirect, render_template, request, url_for +from flask import ( + abort, + current_app, + jsonify, + redirect, + render_template, + request, + url_for, +) from flask_login import current_user from app import redis_client, status_api_client @@ -10,6 +18,7 @@ from app.main import main from app.main.views.pricing import CURRENT_SMS_RATE from app.main.views.sub_navigation_dictionaries import ( + about_notify_nav, best_practices_nav, features_nav, using_notify_nav, @@ -18,18 +27,33 @@ from notifications_utils.url_safe_token import generate_token -# Hook to check for guidance routes +# Hook to check for feature flags @main.before_request -def check_guidance_feature(): - current_app.logger.warning("best practices 1234") - current_app.logger.warning(current_app.config["FEATURE_BEST_PRACTICES_ENABLED"]) +def check_feature_flags(): + if ( + request.path.startswith("/guides/best-practices") + and not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED", False) + ): + abort(404) + if ( - request.path.startswith("/best-practices") - and not current_app.config["FEATURE_BEST_PRACTICES_ENABLED"] + request.path.startswith("/about") + and not current_app.config.get("FEATURE_ABOUT_PAGE_ENABLED", False) ): abort(404) +@main.route("/test/feature-flags") +def test_feature_flags(): + return jsonify( + { + "FEATURE_BEST_PRACTICES_ENABLED": current_app.config[ + "FEATURE_BEST_PRACTICES_ENABLED" + ] + } + ) + + @main.route("/") def index(): if current_user and current_user.is_authenticated: @@ -207,7 +231,7 @@ def trial_mode_new(): ) -@main.route("/best-practices") +@main.route("/guides/best-practices") @user_is_logged_in def best_practices(): return render_template( @@ -216,7 +240,7 @@ def best_practices(): ) -@main.route("/best-practices/clear-goals") +@main.route("/guides/best-practices/clear-goals") @user_is_logged_in def clear_goals(): return render_template( @@ -225,7 +249,7 @@ def clear_goals(): ) -@main.route("/best-practices/rules-and-regulations") +@main.route("/guides/best-practices/rules-and-regulations") @user_is_logged_in def rules_and_regulations(): return render_template( @@ -234,7 +258,7 @@ def rules_and_regulations(): ) -@main.route("/best-practices/establish-trust") +@main.route("/guides/best-practices/establish-trust") @user_is_logged_in def establish_trust(): return render_template( @@ -243,7 +267,7 @@ def establish_trust(): ) -@main.route("/best-practices/write-for-action") +@main.route("/guides/best-practices/write-for-action") @user_is_logged_in def write_for_action(): return render_template( @@ -252,7 +276,7 @@ def write_for_action(): ) -@main.route("/best-practices/multiple-languages") +@main.route("/guides/best-practices/multiple-languages") @user_is_logged_in def multiple_languages(): return render_template( @@ -261,7 +285,7 @@ def multiple_languages(): ) -@main.route("/best-practices/benchmark-performance") +@main.route("/guides/best-practices/benchmark-performance") @user_is_logged_in def benchmark_performance(): return render_template( @@ -270,7 +294,7 @@ def benchmark_performance(): ) -@main.route("/using-notify/guidance") +@main.route("/guides/using-notify/guidance") @user_is_logged_in def guidance_index(): return render_template( @@ -282,6 +306,14 @@ def guidance_index(): ) +@main.route("/about") +def about_notify(): + return render_template( + "views/about/about.html", + navigation_links=about_notify_nav(), + ) + + @main.route("/using-notify/guidance/create-and-send-messages") @user_is_logged_in def create_and_send_messages(): diff --git a/app/main/views/sub_navigation_dictionaries.py b/app/main/views/sub_navigation_dictionaries.py index 0689c198d4..b9fb7f8aef 100644 --- a/app/main/views/sub_navigation_dictionaries.py +++ b/app/main/views/sub_navigation_dictionaries.py @@ -27,6 +27,10 @@ def using_notify_nav(): "name": "Get started", "link": "main.get_started", }, + { + "name": "Guides", + "link": "main.best_practices", + }, { "name": "Trial mode", "link": "main.trial_mode_new", @@ -101,3 +105,12 @@ def best_practices_nav(): "link": "main.benchmark_performance", }, ] + + +def about_notify_nav(): + return [ + { + "name": "About notify", + "link": "main.about_notify", + }, + ] diff --git a/app/navigation.py b/app/navigation.py index 6ef0907a68..a02df484df 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -46,6 +46,15 @@ class HeaderNavigation(Navigation): "roadmap", "security", }, + "best_practices": { + "best_practices", + "clear_goals", + "rules_and_regulations", + "establish_trust", + "write_for_action", + "multiple_languages", + "benchmark_performance" + }, "using_notify": { "get_started", "using_notify", diff --git a/app/templates/components/folder-path.html b/app/templates/components/folder-path.html index c686702ba4..b6615a2da7 100644 --- a/app/templates/components/folder-path.html +++ b/app/templates/components/folder-path.html @@ -22,7 +22,7 @@ {{ folder.name }} {% endif %} {% else %} - Templates + Templates {% endif %} {% if not loop.last %}{{ folder_path_separator() }}{% endif %} {% endif %} diff --git a/app/templates/components/header.html b/app/templates/components/header.html index 5ae37fc714..248abf2508 100644 --- a/app/templates/components/header.html +++ b/app/templates/components/header.html @@ -1,32 +1,43 @@ {% if current_user.is_authenticated %} - {% set navigation = [ - {"href": url_for("main.show_accounts_or_dashboard"), "text": "Current service", "active": header_navigation.is_selected('accounts-or-dashboard')}, - {"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')}, - {"href": url_for('main.features'), "text": "Features", "active": header_navigation.is_selected('features')}, - {"href": url_for('main.support'), "text": "Contact us", "active": header_navigation.is_selected('support')} - ] %} +{% set navigation = [ +{"href": url_for("main.show_accounts_or_dashboard"), "text": "Current service", "active": +header_navigation.is_selected('accounts-or-dashboard')}, +{"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')} +] %} - {% if current_user.platform_admin %} - {% set navigation = navigation + [{"href": url_for('main.platform_admin_splash_page'), "text": "Platform admin", "active": header_navigation.is_selected('platform-admin')}] %} - {% else %} - {% set navigation = navigation + [{"href": url_for('main.user_profile'), "text": "User profile", "active": header_navigation.is_selected('user-profile')}] %} - {% endif %} +{% if FEATURE_BEST_PRACTICES_ENABLED %} +{% set navigation = navigation + [{"href": url_for('main.best_practices'), "text": "Guides", "active": +header_navigation.is_selected('best_practices')}] %} +{% endif %} + +{% set navigation = navigation + [ +{"href": url_for('main.features'), "text": "Features", "active": header_navigation.is_selected('features')}, +{"href": url_for('main.support'), "text": "Contact us", "active": header_navigation.is_selected('support')} +] %} - {% if current_service %} - {% if current_user.has_permissions('manage_service') %} - {% set secondaryNavigation = [ - {"href": url_for('main.service_settings', service_id=current_service.id), "text": "Settings", "active": secondary_navigation.is_selected('settings')}, - {"href": url_for('main.sign_out'), "text": "Sign out"} - ] %} - {% else %} - {% set secondaryNavigation = [ - {"href": url_for('main.sign_out'), "text": "Sign out"} - ] %} +{% if current_user.platform_admin %} +{% set navigation = navigation + [{"href": url_for('main.platform_admin_splash_page'), "text": "Platform admin", +"active": header_navigation.is_selected('platform-admin')}] %} +{% else %} +{% set navigation = navigation + [{"href": url_for('main.user_profile'), "text": "User profile", "active": +header_navigation.is_selected('user-profile')}] %} +{% endif %} - {% endif %} - {% else %} - {% set secondaryNavigation = [{"href": url_for('main.sign_out'), "text": "Sign out"}] %} - {% endif %} +{% if current_service %} +{% if current_user.has_permissions('manage_service') %} +{% set secondaryNavigation = [ +{"href": url_for('main.service_settings', service_id=current_service.id), "text": "Settings", "active": +secondary_navigation.is_selected('settings')}, +{"href": url_for('main.sign_out'), "text": "Sign out"} +] %} +{% else %} +{% set secondaryNavigation = [ +{"href": url_for('main.sign_out'), "text": "Sign out"} +] %} +{% endif %} +{% else %} +{% set secondaryNavigation = [{"href": url_for('main.sign_out'), "text": "Sign out"}] %} +{% endif %} {% endif %}
@@ -36,12 +47,12 @@
Notify.gov logo - - +
{% if navigation %} - + {% endif %} @@ -52,29 +63,29 @@
diff --git a/app/templates/partials/jobs/notifications.html b/app/templates/partials/jobs/notifications.html index 379a8efef9..6df3085ee0 100644 --- a/app/templates/partials/jobs/notifications.html +++ b/app/templates/partials/jobs/notifications.html @@ -2,7 +2,7 @@ {% from "components/page-footer.html" import page_footer %} {% from "components/form.html" import form_wrapper %} -
+
{% if job.scheduled %}

diff --git a/app/templates/views/about/about.html b/app/templates/views/about/about.html new file mode 100644 index 0000000000..39dfce6717 --- /dev/null +++ b/app/templates/views/about/about.html @@ -0,0 +1,77 @@ +{% extends "base.html" %} + +{% set page_title = "About notify" %} + +{% block per_page_title %} +{{page_title}} +{% endblock %} + +{% block content_column_content %} + +

+

{{page_title}}

+

Notify.gov is a text messaging service built by and for the government. We help agencies communicate more + effectively with the people they serve. With Notify.gov, federal and federally-funded programs can send customized + text messages that make it possible to:

+
    +
  • Meet people where they are
  • +
  • More effectively deliver program outcomes
  • +
  • Save administrative costs
  • +
  • Implement 21st Century IDEA and other directives
  • +
+

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 + by minimizing data retention and using modern encryption methods.

+ +

Product Highlights

+ {% set product_highlights = [ + { + "svg_src": "#send", + "card_heading": "Send customized one-way customized messages", + "p_text": "Upload a file with recipient phone numbers and Notify.gov sends customized messages", + }, + { + "svg_src": "#translate", + "card_heading": "Send in recipients’ preferred language", + "p_text": "Notify.gov supports more than 30 character sets to send messages in almost any language", + }, + { + "svg_src": "#trending_up", + "card_heading": "See how messages perform", + "p_text": "Track how many messages you’ve sent and monitor delivery rates", + }, + { + "svg_src": "#add", + "card_heading": "Create and manage multiple services within a single organization", + "p_text": "Set up individual workspaces for different texting services, allowing multiple teams or programs to manage + day-to-day texting operations across an organization", + }, + { + "svg_src": "#people", + "card_heading": "Manage team member and permissions on each service", + "p_text": "Administrators can add users and control what they can do in Notify.gov", + } + ] %} +
    + {% for item in product_highlights %} +
  • +
    +
    + + {{item.card_heading}} +
    +

    {{item.p_text}}

    +
    +
  • + {% endfor %} +
+

See if Notify is right for you

+

Notify.gov is a product of the Public Benefits Studio, a product accelerator inside + the federal government.

+ + +
+{% endblock %} diff --git a/app/templates/views/best-practices/best-practices.html b/app/templates/views/best-practices/best-practices.html index a00a486600..7711dea9bb 100644 --- a/app/templates/views/best-practices/best-practices.html +++ b/app/templates/views/best-practices/best-practices.html @@ -23,37 +23,37 @@

"svg_src": "goal", "card_heading": "Establish clear goals", "p_text": "Start with a singular purpose. Make explicit what you want to achieve.", - "link": "/best-practices/clear-goals" + "link": "/guides/best-practices/clear-goals" }, { "svg_src": "compliant", "card_heading": "Follow rules & regulations", "p_text": "Understand what is required when texting the public.", - "link": "/best-practices/rules-and-regulations" + "link": "/guides/best-practices/rules-and-regulations" }, { "svg_src": "trust", "card_heading": "Establish trust", "p_text": "Help your audience anticipate and welcome your texts.", - "link": "/best-practices/establish-trust" + "link": "/guides/best-practices/establish-trust" }, { "svg_src": "runner", "card_heading": "Write texts that provoke action", "p_text": "Help your audience know what to do with the information you send.", - "link": "/best-practices/write-for-action" + "link": "/guides/best-practices/write-for-action" }, { "svg_src": "language", "card_heading": "Send texts in multiple languages", "p_text": "What to know as you plan translated texts.", - "link": "/best-practices/multiple-languages" + "link": "/guides/best-practices/multiple-languages" }, { "svg_src": "chart", "card_heading": "Measure performance with benchmarking", "p_text": "Learn how effective your texting program can be.", - "link": "/best-practices/benchmark-performance" + "link": "/guides/best-practices/benchmark-performance" } ] %} diff --git a/package-lock.json b/package-lock.json index 64db0c2705..24320a21e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/stream": "^3.0.1", - "@uswds/uswds": "^3.9.0", + "@uswds/uswds": "^3.10.0", "cbor-js": "0.1.0", "d3": "^7.9.0", "govuk_frontend_toolkit": "^9.0.1", @@ -21,10 +21,10 @@ "hogan": "1.0.2", "jquery": "3.7.1", "morphdom": "^2.7.4", - "playwright": "^1.48.2", + "playwright": "^1.49.0", "python": "^0.0.4", "query-command-supported": "1.0.0", - "sass-embedded": "^1.80.6", + "sass-embedded": "^1.81.0", "textarea-caret": "3.1.0", "timeago": "1.6.7", "vinyl-buffer": "^1.0.1", @@ -50,7 +50,7 @@ "jest-environment-jsdom": "^29.2.2", "jshint": "2.13.6", "jshint-stylish": "2.2.1", - "rollup": "^4.24.4", + "rollup": "^4.27.3", "rollup-plugin-commonjs": "10.1.0", "rollup-plugin-node-resolve": "5.2.0" }, @@ -2667,9 +2667,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", - "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.3.tgz", + "integrity": "sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==", "cpu": [ "arm" ], @@ -2679,9 +2679,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", - "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.3.tgz", + "integrity": "sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==", "cpu": [ "arm64" ], @@ -2691,9 +2691,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", - "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.3.tgz", + "integrity": "sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==", "cpu": [ "arm64" ], @@ -2703,9 +2703,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", - "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.3.tgz", + "integrity": "sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==", "cpu": [ "x64" ], @@ -2715,9 +2715,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", - "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.3.tgz", + "integrity": "sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==", "cpu": [ "arm64" ], @@ -2727,9 +2727,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", - "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.3.tgz", + "integrity": "sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==", "cpu": [ "x64" ], @@ -2739,9 +2739,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", - "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.3.tgz", + "integrity": "sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==", "cpu": [ "arm" ], @@ -2751,9 +2751,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", - "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.3.tgz", + "integrity": "sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==", "cpu": [ "arm" ], @@ -2763,9 +2763,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", - "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.3.tgz", + "integrity": "sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==", "cpu": [ "arm64" ], @@ -2775,9 +2775,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", - "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.3.tgz", + "integrity": "sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==", "cpu": [ "arm64" ], @@ -2787,9 +2787,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", - "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.3.tgz", + "integrity": "sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==", "cpu": [ "ppc64" ], @@ -2799,9 +2799,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", - "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.3.tgz", + "integrity": "sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==", "cpu": [ "riscv64" ], @@ -2811,9 +2811,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", - "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.3.tgz", + "integrity": "sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==", "cpu": [ "s390x" ], @@ -2823,9 +2823,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", - "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.3.tgz", + "integrity": "sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==", "cpu": [ "x64" ], @@ -2835,9 +2835,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", - "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.3.tgz", + "integrity": "sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==", "cpu": [ "x64" ], @@ -2847,9 +2847,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", - "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.3.tgz", + "integrity": "sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==", "cpu": [ "arm64" ], @@ -2859,9 +2859,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", - "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.3.tgz", + "integrity": "sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==", "cpu": [ "ia32" ], @@ -2871,9 +2871,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", - "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.3.tgz", + "integrity": "sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==", "cpu": [ "x64" ], @@ -3485,11 +3485,10 @@ } }, "node_modules/@uswds/uswds": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.9.0.tgz", - "integrity": "sha512-8THm36j7iLjrDiI1D0C6b3hHsmM/Sy5Iiz+IjE+i/gYzVUMG9XVthxAZYonhU97Q1b079n6nYwlUmDSYowJecQ==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.10.0.tgz", + "integrity": "sha512-LWFTQzp4e3kqtnD/Wsyfx9uGTkn5GEpzhscNWJMIsdWBGKtiu96QT99oRJUmcsB6HbGhR0Th0FtlK/Zzx2WghA==", "dependencies": { - "object-assign": "4.1.1", "receptor": "1.0.0", "resolve-id-refs": "0.1.0" }, @@ -8314,7 +8313,8 @@ "node_modules/immutable": { "version": "4.3.6", "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": { "version": "3.3.0", @@ -12011,11 +12011,11 @@ } }, "node_modules/playwright": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", - "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz", + "integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==", "dependencies": { - "playwright-core": "1.48.2" + "playwright-core": "1.49.0" }, "bin": { "playwright": "cli.js" @@ -12028,9 +12028,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", - "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz", + "integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==", "bin": { "playwright-core": "cli.js" }, @@ -12951,9 +12951,9 @@ "license": "Unlicense" }, "node_modules/rollup": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", - "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", + "version": "4.27.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.3.tgz", + "integrity": "sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==", "dependencies": { "@types/estree": "1.0.6" }, @@ -12965,24 +12965,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.4", - "@rollup/rollup-android-arm64": "4.24.4", - "@rollup/rollup-darwin-arm64": "4.24.4", - "@rollup/rollup-darwin-x64": "4.24.4", - "@rollup/rollup-freebsd-arm64": "4.24.4", - "@rollup/rollup-freebsd-x64": "4.24.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.4", - "@rollup/rollup-linux-arm-musleabihf": "4.24.4", - "@rollup/rollup-linux-arm64-gnu": "4.24.4", - "@rollup/rollup-linux-arm64-musl": "4.24.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", - "@rollup/rollup-linux-riscv64-gnu": "4.24.4", - "@rollup/rollup-linux-s390x-gnu": "4.24.4", - "@rollup/rollup-linux-x64-gnu": "4.24.4", - "@rollup/rollup-linux-x64-musl": "4.24.4", - "@rollup/rollup-win32-arm64-msvc": "4.24.4", - "@rollup/rollup-win32-ia32-msvc": "4.24.4", - "@rollup/rollup-win32-x64-msvc": "4.24.4", + "@rollup/rollup-android-arm-eabi": "4.27.3", + "@rollup/rollup-android-arm64": "4.27.3", + "@rollup/rollup-darwin-arm64": "4.27.3", + "@rollup/rollup-darwin-x64": "4.27.3", + "@rollup/rollup-freebsd-arm64": "4.27.3", + "@rollup/rollup-freebsd-x64": "4.27.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.3", + "@rollup/rollup-linux-arm-musleabihf": "4.27.3", + "@rollup/rollup-linux-arm64-gnu": "4.27.3", + "@rollup/rollup-linux-arm64-musl": "4.27.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.3", + "@rollup/rollup-linux-riscv64-gnu": "4.27.3", + "@rollup/rollup-linux-s390x-gnu": "4.27.3", + "@rollup/rollup-linux-x64-gnu": "4.27.3", + "@rollup/rollup-linux-x64-musl": "4.27.3", + "@rollup/rollup-win32-arm64-msvc": "4.27.3", + "@rollup/rollup-win32-ia32-msvc": "4.27.3", + "@rollup/rollup-win32-x64-msvc": "4.27.3", "fsevents": "~2.3.2" } }, @@ -13091,16 +13091,17 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass-embedded": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.80.6.tgz", - "integrity": "sha512-Og4aqBnaA3oJfIpHaLuNATAqzBRgUJDYJy2X15V59cot2wYOtiT/ciPnyuq1o7vpDEeOkHhEd+mSviSlXoETug==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.81.0.tgz", + "integrity": "sha512-uZQ2Faxb1oWBHpeSSzjxnhClbMb3QadN0ql0ZFNuqWOLUxwaVhrMlMhPq6TDPbbfDUjihuwrMCuy695Bgna5RA==", "dependencies": { "@bufbuild/protobuf": "^2.0.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", - "immutable": "^4.0.0", + "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "bin": { @@ -13110,32 +13111,32 @@ "node": ">=16.0.0" }, "optionalDependencies": { - "sass-embedded-android-arm": "1.80.6", - "sass-embedded-android-arm64": "1.80.6", - "sass-embedded-android-ia32": "1.80.6", - "sass-embedded-android-riscv64": "1.80.6", - "sass-embedded-android-x64": "1.80.6", - "sass-embedded-darwin-arm64": "1.80.6", - "sass-embedded-darwin-x64": "1.80.6", - "sass-embedded-linux-arm": "1.80.6", - "sass-embedded-linux-arm64": "1.80.6", - "sass-embedded-linux-ia32": "1.80.6", - "sass-embedded-linux-musl-arm": "1.80.6", - "sass-embedded-linux-musl-arm64": "1.80.6", - "sass-embedded-linux-musl-ia32": "1.80.6", - "sass-embedded-linux-musl-riscv64": "1.80.6", - "sass-embedded-linux-musl-x64": "1.80.6", - "sass-embedded-linux-riscv64": "1.80.6", - "sass-embedded-linux-x64": "1.80.6", - "sass-embedded-win32-arm64": "1.80.6", - "sass-embedded-win32-ia32": "1.80.6", - "sass-embedded-win32-x64": "1.80.6" + "sass-embedded-android-arm": "1.81.0", + "sass-embedded-android-arm64": "1.81.0", + "sass-embedded-android-ia32": "1.81.0", + "sass-embedded-android-riscv64": "1.81.0", + "sass-embedded-android-x64": "1.81.0", + "sass-embedded-darwin-arm64": "1.81.0", + "sass-embedded-darwin-x64": "1.81.0", + "sass-embedded-linux-arm": "1.81.0", + "sass-embedded-linux-arm64": "1.81.0", + "sass-embedded-linux-ia32": "1.81.0", + "sass-embedded-linux-musl-arm": "1.81.0", + "sass-embedded-linux-musl-arm64": "1.81.0", + "sass-embedded-linux-musl-ia32": "1.81.0", + "sass-embedded-linux-musl-riscv64": "1.81.0", + "sass-embedded-linux-musl-x64": "1.81.0", + "sass-embedded-linux-riscv64": "1.81.0", + "sass-embedded-linux-x64": "1.81.0", + "sass-embedded-win32-arm64": "1.81.0", + "sass-embedded-win32-ia32": "1.81.0", + "sass-embedded-win32-x64": "1.81.0" } }, "node_modules/sass-embedded-android-arm": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.80.6.tgz", - "integrity": "sha512-UeUKMTRsnz4/dh7IzvhjONxa4/jmVp539CHDd8VZOsqg9M3HcNJNIkUzQWbuwZ+nSlWrTuo7Tvn3XlypopCBzw==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.81.0.tgz", + "integrity": "sha512-NWEmIuaIEsGFNsIRa+5JpIpPJyZ32H15E85CNZqEIhhwWlk9UNw7vlOCmTH8MtabtnACwC/2NG8VyNa3nxKzUQ==", "cpu": [ "arm" ], @@ -13148,9 +13149,9 @@ } }, "node_modules/sass-embedded-android-arm64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.80.6.tgz", - "integrity": "sha512-4rC4ZGM/k4ENVjLXnK3JTst8e8FI9MHSol2Fl7dCdYyJ3KLnlt4qL4AEYfU8zq1tcBb7CBOSZVR+CzCKubnXdg==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.81.0.tgz", + "integrity": "sha512-I36P77/PKAHx6sqOmexO2iEY5kpsmQ1VxcgITZSOxPMQhdB6m4t3bTabfDuWQQmCrqqiNFtLQHeytB65bUqwiw==", "cpu": [ "arm64" ], @@ -13163,9 +13164,9 @@ } }, "node_modules/sass-embedded-android-ia32": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.80.6.tgz", - "integrity": "sha512-Lxz2SXE2KdHnynuHF+D6flDvrd55/zaEAWUeka9MxEr6FmR66d8UBOIy5ETwCSUd//S/SE5Jl6oTnHppgD1zNA==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.81.0.tgz", + "integrity": "sha512-k8V1usXw30w1GVxvrteG1RzgYJzYQ9PfL2aeOqGdroBN7zYTD9VGJXTGcxA4IeeRxmRd7szVW2mKXXS472fh8g==", "cpu": [ "ia32" ], @@ -13178,9 +13179,9 @@ } }, "node_modules/sass-embedded-android-riscv64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.80.6.tgz", - "integrity": "sha512-hKdxY/oOqB+JJhSoBTDM5DJO1j/xtxQgayh2cLCCUx37IQQe3SEdc3V2JFf/4mIo5peaS4cjqwwSATF+l2zaXg==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.81.0.tgz", + "integrity": "sha512-RXlanyLXEpN/DEehXgLuKPsqT//GYlsGFxKXgRiCc8hIPAueFLQXKJmLWlL3BEtHgmFdbsStIu4aZCcb1hOFlQ==", "cpu": [ "riscv64" ], @@ -13193,9 +13194,9 @@ } }, "node_modules/sass-embedded-android-x64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.80.6.tgz", - "integrity": "sha512-Eap2Fi3kTx/rVLBsOnOp5RYPr5+lFjTZ652zR24dmYFe9/sDgasakJIOPjOvD2bRuL9z0uWEY1AXVeeOPeZKrg==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.81.0.tgz", + "integrity": "sha512-RQG0FxGQ1DERNyUDED8+BDVaLIjI+BNg8lVcyqlLZUrWY6NhzjwYEeiN/DNZmMmHtqDucAPNDcsdVUNQqsBy2A==", "cpu": [ "x64" ], @@ -13208,9 +13209,9 @@ } }, "node_modules/sass-embedded-darwin-arm64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.80.6.tgz", - "integrity": "sha512-0mnAx8Vq6Gxj3PQt3imgITfK33hhqrSKpyHSuab71gZZni5opsdtoggq2JawW+1taRFTEZwbZJLKZ0MBDbwCCA==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.81.0.tgz", + "integrity": "sha512-gLKbsfII9Ppua76N41ODFnKGutla9qv0OGAas8gxe0jYBeAQFi/1iKQYdNtQtKi4mA9n5TQTqz+HHCKszZCoyA==", "cpu": [ "arm64" ], @@ -13223,9 +13224,9 @@ } }, "node_modules/sass-embedded-darwin-x64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.80.6.tgz", - "integrity": "sha512-Ib20yNZFOrJ7YVT+ltoe+JQNKPcRclM3iLAK69XZZYcSeFM/72SCoQBAaVGIpT23dxDp7FXiE4lO602c3xTRwQ==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.81.0.tgz", + "integrity": "sha512-7uMOlT9hD2KUJCbTN2XcfghDxt/rc50ujjfSjSHjX1SYj7mGplkINUXvVbbvvaV2wt6t9vkGkCo5qNbeBhfwBg==", "cpu": [ "x64" ], @@ -13238,9 +13239,9 @@ } }, "node_modules/sass-embedded-linux-arm": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.80.6.tgz", - "integrity": "sha512-QR0Q6TZox/ThuU2r9c0s3fKCgU2rXAEocpitdgxFp6tta+GsQlMFV3oON2unAa8Bwnuxkmf0YOaK0Oy/TwzkXw==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.81.0.tgz", + "integrity": "sha512-REqR9qM4RchCE3cKqzRy9Q4zigIV82SbSpCi/O4O3oK3pg2I1z7vkb3TiJsivusG/li7aqKZGmYOtAXjruGQDA==", "cpu": [ "arm" ], @@ -13253,9 +13254,9 @@ } }, "node_modules/sass-embedded-linux-arm64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.80.6.tgz", - "integrity": "sha512-n5r98pBXawrQQKaxIYCMM1zDpnngsqxTkOrmvsYLFiAMCSbR0lWf/7sBB33k/Pm0D6dsbp3jpHilCoQNKI3jIw==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.81.0.tgz", + "integrity": "sha512-jy4bvhdUmqbyw1jv1f3Uxl+MF8EU/Y/GDx4w6XPJm4Ds+mwH/TwnyAwsxxoBhWfnBnW8q2ADy039DlS5p+9csQ==", "cpu": [ "arm64" ], @@ -13268,9 +13269,9 @@ } }, "node_modules/sass-embedded-linux-ia32": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.80.6.tgz", - "integrity": "sha512-O6dWZdcOkryRdDCxVMGOeVowgblpDgVcAuRtZ1F1X7XfbpDriTQm64D+9vVZIrywYSPoJfQMJJ662cr0wUs9IQ==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.81.0.tgz", + "integrity": "sha512-ga/Jk4q5Bn1aC+iHJteDZuLSKnmBUiS3dEg1fnl/Z7GaHIChceKDJOw0zNaILRXI0qT2E1at9MwzoRaRA5Nn/g==", "cpu": [ "ia32" ], @@ -13283,9 +13284,9 @@ } }, "node_modules/sass-embedded-linux-musl-arm": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.80.6.tgz", - "integrity": "sha512-X9FC8s8fvQGRiXc+eATlZ57N44Iq3nNa0M0ugi3ysdJwkaNYvOeS4QzBHKQAaw3QiTqdxTnLUHHVBkyzdCi9pw==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.81.0.tgz", + "integrity": "sha512-oWVUvQ4d5Kx1Md75YXZl5z1WBjc+uOhfRRqzkJ3nWc8tjszxJN+y/5EOJavhsNI3/2yoTt6eMXRTqDD9b0tWSQ==", "cpu": [ "arm" ], @@ -13298,9 +13299,9 @@ } }, "node_modules/sass-embedded-linux-musl-arm64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.80.6.tgz", - "integrity": "sha512-VeUSHUi3MAsvOlg9QI4X/2j04h1659aE+7qKP/282CYBTrGkjFGSXZhIki9WKWDgIpDiSInRYXfQQRWhPhjCDg==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.81.0.tgz", + "integrity": "sha512-hpntWf5kjkoxncA1Vh8vhsUOquZ8AROZKx0rQh7ZjSRs4JrYZASz1cfevPKaEM3wIim/nYa6TJqm0VqWsrERlA==", "cpu": [ "arm64" ], @@ -13313,9 +13314,9 @@ } }, "node_modules/sass-embedded-linux-musl-ia32": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.80.6.tgz", - "integrity": "sha512-GqitS2Nab8ah0+wfCqaxW1hnI1piC08FimL6+lM9YWK5DbCOOF82IapbvJOy0feUmd/wNnHmyNTgE9h0zVMFdQ==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.81.0.tgz", + "integrity": "sha512-UEXUYkBuqTSwg5JNWiNlfMZ1Jx6SJkaEdx+fsL3Tk099L8cKSoJWH2EPz4ZJjNbyIMymrSdVfymheTeZ8u24xA==", "cpu": [ "ia32" ], @@ -13328,9 +13329,9 @@ } }, "node_modules/sass-embedded-linux-musl-riscv64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.80.6.tgz", - "integrity": "sha512-ySs15z7QSRRQK/aByEEqaJLYW/sTpfynefNPZCtsVNVEzNRwy+DRpxNChtxo+QjKq97ocXETbdG5KLik7QOTJg==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.81.0.tgz", + "integrity": "sha512-1D7OznytbIhx2XDHWi1nuQ8d/uCVR7FGGzELgaU//T8A9DapVTUgPKvB70AF1k4GzChR9IXU/WvFZs2hDTbaJg==", "cpu": [ "riscv64" ], @@ -13343,9 +13344,9 @@ } }, "node_modules/sass-embedded-linux-musl-x64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.80.6.tgz", - "integrity": "sha512-DzeNqU/SN0mWFznoOH4RtVGcrg3Eoa41pUQhKMtrhNbCmIE1zNDunUiAEVTNpdHJF4nxf7ELUPXWmStM31CbUQ==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.81.0.tgz", + "integrity": "sha512-ia6VCTeVDQtBSMktXRFza1AZCt8/6aUoujot6Ugf4KmdytQqPJIHxkHaGftm5xwi9WdrMGYS7zgolToPijR11A==", "cpu": [ "x64" ], @@ -13358,9 +13359,9 @@ } }, "node_modules/sass-embedded-linux-riscv64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.80.6.tgz", - "integrity": "sha512-AyoHJ3icV9xuJjq1YzJqpEj2XfiC/KBkVYTUrCELKiXP0DN1gi/BpUwZNCAgCM3CyEdMef4LQM/ztCYJxYzdyg==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.81.0.tgz", + "integrity": "sha512-KbxSsqu4tT1XbhZfJV/5NfW0VtJIGlD58RjqJqJBi8Rnjrx29/upBsuwoDWtsPV/LhoGwwU1XkSa9Q1ifCz4fQ==", "cpu": [ "riscv64" ], @@ -13373,9 +13374,9 @@ } }, "node_modules/sass-embedded-linux-x64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.80.6.tgz", - "integrity": "sha512-EohsE9CEqx0ycylnsEj/0DNPG99Tb0qAVZspiAs5xHFCJjXOFfp3cRQu0BRf+lZ1b72IhPFXymzVtojvzUHb7g==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.81.0.tgz", + "integrity": "sha512-AMDeVY2T9WAnSFkuQcsOn5c29GRs/TuqnCiblKeXfxCSKym5uKdBl/N7GnTV6OjzoxiJBbkYKdVIaS5By7Gj4g==", "cpu": [ "x64" ], @@ -13388,9 +13389,9 @@ } }, "node_modules/sass-embedded-win32-arm64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.80.6.tgz", - "integrity": "sha512-29wETQi1ykeVvpd4zMVokpQKFSOZskGJzZawuuNCdo7BHjHKIRDsqbz8YT1CewHPBshI0hfD21fenmjxYjGXPQ==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.81.0.tgz", + "integrity": "sha512-YOmBRYnygwWUmCoH14QbMRHjcvCJufeJBAp0m61tOJXIQh64ziwV4mjdqjS/Rx3zhTT4T+nulDUw4d3kLiMncA==", "cpu": [ "arm64" ], @@ -13403,9 +13404,9 @@ } }, "node_modules/sass-embedded-win32-ia32": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.80.6.tgz", - "integrity": "sha512-1s3OpK2iTIfIL/a91QhAQnffsbuWfnsM8Lx4Fxt0f7ErnxjCV6q8MUFTV/UhcLtLyTFnPCA62DLjp2KGCjMI9A==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.81.0.tgz", + "integrity": "sha512-HFfr/C+uLJGGTENdnssuNTmXI/xnIasUuEHEKqI+2J0FHCWT5cpz3PGAOHymPyJcZVYGUG/7gIxIx/d7t0LFYw==", "cpu": [ "ia32" ], @@ -13418,9 +13419,9 @@ } }, "node_modules/sass-embedded-win32-x64": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.80.6.tgz", - "integrity": "sha512-0pH4Zr9silHkcmLPC0ghnD3DI0vMsjA7dKvGR32/RbbjOSvHV5cDQRLiuVJAPp34dfMA7kJd1ysSchRdH0igAQ==", + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.81.0.tgz", + "integrity": "sha512-wxj52jDcIAwWcXb7ShZ7vQYKcVUkJ+04YM9l46jDY+qwHzliGuorAUyujLyKTE9heGD3gShJ3wPPC1lXzq6v9A==", "cpu": [ "x64" ], @@ -13445,6 +13446,11 @@ "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": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -13994,6 +14000,25 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "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": { "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", diff --git a/package.json b/package.json index ae76a1849a..ace12d6e56 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/stream": "^3.0.1", - "@uswds/uswds": "^3.9.0", + "@uswds/uswds": "^3.10.0", "cbor-js": "0.1.0", "d3": "^7.9.0", "govuk_frontend_toolkit": "^9.0.1", @@ -37,10 +37,10 @@ "hogan": "1.0.2", "jquery": "3.7.1", "morphdom": "^2.7.4", - "playwright": "^1.48.2", + "playwright": "^1.49.0", "python": "^0.0.4", "query-command-supported": "1.0.0", - "sass-embedded": "^1.80.6", + "sass-embedded": "^1.81.0", "textarea-caret": "3.1.0", "timeago": "1.6.7", "vinyl-buffer": "^1.0.1", @@ -66,7 +66,7 @@ "jest-environment-jsdom": "^29.2.2", "jshint": "2.13.6", "jshint-stylish": "2.2.1", - "rollup": "^4.24.4", + "rollup": "^4.27.3", "rollup-plugin-commonjs": "10.1.0", "rollup-plugin-node-resolve": "5.2.0" } diff --git a/tests/app/test_navigation.py b/tests/app/test_navigation.py index 8bf52d8036..af7b7a1588 100644 --- a/tests/app/test_navigation.py +++ b/tests/app/test_navigation.py @@ -17,6 +17,7 @@ map( Navigation.get_endpoint_with_blueprint, { + "about_notify", "accept_invite", "accept_org_invite", "accessibility_statement", @@ -217,6 +218,7 @@ "suspend_service", "template_history", "template_usage", + "test_feature_flags", "tour_step", "trial_mode", "trial_mode_new", diff --git a/tests/end_to_end/test_best_practices_content_pages.py b/tests/end_to_end/test_best_practices_content_pages.py new file mode 100644 index 0000000000..962100de3c --- /dev/null +++ b/tests/end_to_end/test_best_practices_content_pages.py @@ -0,0 +1,72 @@ +import os +import re + +from playwright.sync_api import expect + +from tests.end_to_end.conftest import check_axe_report + +E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI") + + +def test_best_practices_side_menu(authenticated_page): + page = authenticated_page + + page.goto(f"{E2E_TEST_URI}/best-practices") + + page.wait_for_load_state("domcontentloaded") + check_axe_report(page) + + response = page.request.get(f"{E2E_TEST_URI}/test/feature-flags") + feature_flags = response.json() + feature_best_practices_enabled = feature_flags.get("FEATURE_BEST_PRACTICES_ENABLED") + + if feature_best_practices_enabled: + page.get_by_role("link", name="Best Practices").click() + expect(page).to_have_title(re.compile("Best Practice")) + + page.get_by_role("link", name="Clear goals", exact=True).click() + expect(page).to_have_title(re.compile("Establish clear goals")) + + page.get_by_role("link", name="Rules and regulations").click() + expect(page).to_have_title(re.compile("Rules and regulations")) + + page.get_by_role("link", name="Establish trust").click() + expect(page).to_have_title(re.compile("Establish trust")) + + page.get_by_role("link", name="Write for action").click() + expect(page).to_have_title(re.compile("Write texts that provoke")) + + page.get_by_role("link", name="Multiple languages").click() + expect(page).to_have_title(re.compile("Text in multiple languages")) + + page.get_by_role("link", name="Benchmark performance").click() + expect(page).to_have_title(re.compile("Measuring performance with")) + + parent_link = page.get_by_role("link", name="Establish trust") + parent_link.hover() + + submenu_item = page.get_by_role("link", name=re.compile("Get the word out")) + submenu_item.click() + + expect(page).to_have_url(re.compile(r"#get-the-word-out")) + + anchor_target = page.locator("#get-the-word-out") + expect(anchor_target).to_be_visible() + anchor_target.click() + + +def test_breadcrumbs_best_practices(authenticated_page): + page = authenticated_page + + page.goto(f"{E2E_TEST_URI}/best-practices") + + page.wait_for_load_state("domcontentloaded") + check_axe_report(page) + + response = page.request.get(f"{E2E_TEST_URI}/test/feature-flags") + feature_flags = response.json() + feature_best_practices_enabled = feature_flags.get("FEATURE_BEST_PRACTICES_ENABLED") + + if feature_best_practices_enabled: + page.get_by_role("link", name="Clear goals", exact=True).click() + page.locator("ol").get_by_role("link", name="Best Practices").click() diff --git a/urls.js b/urls.js index 8ff543470a..0440430eca 100644 --- a/urls.js +++ b/urls.js @@ -13,13 +13,25 @@ const sublinks = [ { label: 'Roadmap', path: '/features/roadmap' }, { label: 'Security', path: '/features/security' }, { label: 'Support', path: '/support' }, - { label: 'Best Practices', path: '/best-practices' }, - { label: 'Clear Goals', path: '/best-practices/clear-goals' }, - { label: 'Rules And Regulations', path: '/best-practices/rules-and-regulations' }, - { label: 'Establish Trust', path: '/best-practices/establish-trust' }, - { label: 'Write For Action', path: '/best-practices/write-for-action' }, - { label: 'Multiple Languages', path: '/best-practices/multiple-languages' }, - { label: 'Benchmark Performance', path: '/best-practices/benchmark-performance' }, + { label: 'Best Practices', path: '/guides/best-practices' }, + { label: 'Clear Goals', path: '/guides/best-practices/clear-goals' }, + { + label: 'Rules And Regulations', + path: '/guides/best-practices/rules-and-regulations', + }, + { label: 'Establish Trust', path: '/guides/best-practices/establish-trust' }, + { + label: 'Write For Action', + path: '/guides/best-practices/write-for-action', + }, + { + label: 'Multiple Languages', + path: '/guides/best-practices/multiple-languages', + }, + { + label: 'Benchmark Performance', + path: '/guides/best-practices/benchmark-performance', + }, // Add more links here as needed ];