diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index cb1062e3c..1dc92d63f 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -41,7 +41,13 @@ jobs: - name: Run js tests run: npm test - name: Run py tests with coverage - run: pipenv run coverage run --omit=*/notifications_utils/* -m pytest --maxfail=10 + run: pipenv run coverage run --omit=*/notifications_utils/* -m pytest --maxfail=10 --ignore=tests/end_to_end tests/ + - name: Run E2E tests + run: pipenv run pytest -v --browser chromium --browser firefox --browser webkit tests/end_to_end + env: + NOTIFY_STAGING_HTTP_AUTH_PASSWORD: ${{ secrets.NOTIFY_STAGING_HTTP_AUTH_PASSWORD }} + NOTIFY_STAGING_HTTP_AUTH_USER: ${{ secrets.NOTIFY_STAGING_HTTP_AUTH_USER }} + NOTIFY_STAGING_URI: ${{ secrets.NOTIFY_STAGING_URI }} - name: Check coverage threshold run: pipenv run coverage report --fail-under=90 diff --git a/Makefile b/Makefile index 709e8fe02..079c699c5 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ NVMSH := $(shell [ -f "$(HOME)/.nvm/nvm.sh" ] && echo "$(HOME)/.nvm/nvm.sh" || e .PHONY: bootstrap bootstrap: generate-version-file ## Set up everything to run the app pipenv install --dev + pipenv run playwright install --with-deps source $(NVMSH) --no-use && nvm install && npm ci --no-audit source $(NVMSH) && npm run build @@ -54,10 +55,15 @@ py-lint: ## Run python linting scanners .PHONY: py-test py-test: export NEW_RELIC_ENVIRONMENT=test py-test: ## Run python unit tests - pipenv run coverage run --omit=*/notifications_utils/* -m pytest --maxfail=10 tests/ - pipenv run coverage report --fail-under=90 + pipenv run coverage run --omit=*/notifications_utils/* -m pytest --maxfail=10 --ignore=tests/end_to_end tests/ + pipenv run coverage report --fail-under=96 pipenv run coverage html -d .coverage_cache +.PHONY: e2e-test +e2e-test: export NEW_RELIC_ENVIRONMENT=test +e2e-test: ## Run end-to-end integration tests + pipenv run pytest -v --browser chromium --browser firefox --browser webkit tests/end_to_end + .PHONY: js-lint js-lint: ## Run javascript linting scanners source $(NVMSH) && npm run lint diff --git a/Pipfile b/Pipfile index 4b0e3723f..325e2470d 100644 --- a/Pipfile +++ b/Pipfile @@ -37,6 +37,7 @@ newrelic = "*" flask-talisman = "*" notifications-utils = {editable = true, ref = "main", git = "https://github.com/GSA/notifications-utils.git"} coverage = "*" +pytest-playwright = "*" [dev-packages] isort = "==5.12.0" @@ -47,7 +48,7 @@ pytest-xdist = "==3.3.1" beautifulsoup4 = "==4.12.2" freezegun = "==1.2.2" flake8 = "==6.0.0" -flake8-bugbear = "==23.3.12" +flake8-bugbear = "==23.7.10" flake8-print = "==5.0.0" moto = "~=4.1" requests-mock = "==1.11.0" diff --git a/Pipfile.lock b/Pipfile.lock index 736bf0704..520f7b91c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "e04b206789066f85bd531289b77e299b204d677f52ff65861e7793bcbca053dd" + "sha256": "e6e49305bdee7cdd4605b8f6f7d0135cfe91e0c038abe6efdfa1784194ce3cdd" }, "pipfile-spec": 6, "requires": { @@ -50,19 +50,19 @@ }, "boto3": { "hashes": [ - "sha256:0fe7a35cf0041145c8eefebd3ae2ddf41baed62d7c963e5042b8ed8c297f648f", - "sha256:e24460d50001b517c6734dcf1c879feb43aa2062d88d9bdbb8703c986cb05941" + "sha256:b2d178c8a56fe3e4c9b123dccdff20e9555d12a597b72627fa659aa6295e238a", + "sha256:db6443fd2c65d9f35f671b03bacb0592b62d06884395ed65d75922ccddc34c2e" ], "markers": "python_version >= '3.7'", - "version": "==1.28.11" + "version": "==1.28.13" }, "botocore": { "hashes": [ - "sha256:b17ff973bb70b02b227928c2abe4992f1cfc46d13aee0228516c8f32572b88c6", - "sha256:d3cbffe554c9a1ba2ac6973734c43c21b8e7985a2ac4a4c31a09811b8029445c" + "sha256:78b96afbd88b8bd4c0967611a4cedddd9ea33d8601309dc351f81cbb5479d976", + "sha256:9a5080ea2a444f0447a7a1a79f64252ae2a1417b6c13a54656ee991cb610dd4e" ], "markers": "python_version >= '3.7'", - "version": "==1.31.11" + "version": "==1.31.13" }, "cachetools": { "hashes": [ @@ -556,6 +556,14 @@ "markers": "python_version < '3.10'", "version": "==6.8.0" }, + "iniconfig": { + "hashes": [ + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, "itsdangerous": { "hashes": [ "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", @@ -826,6 +834,14 @@ ], "version": "==2.0.3" }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, "phonenumbers": { "hashes": [ "sha256:89671217c706cbaa3ced101deefafa779836feac3e059434d886ac31f09f32c0", @@ -833,6 +849,27 @@ ], "version": "==8.13.17" }, + "playwright": { + "hashes": [ + "sha256:428a719a6c7e40781c19860ed813840ac2d63678f7587abe12e800ea030d4b7e", + "sha256:4e396853034742b76654cdab27422155d238f46e4dc6369ea75854fafb935586", + "sha256:72e80076e595f5fcd8ebd89bf6635ad78e4bafa633119faed8b2568d17dbd398", + "sha256:84213339f179fd2a70f77ea7faea0616d74871349d556c53a1ecb7dd5097973c", + "sha256:89ca2261bb00b67d3dff97691cf18f4347ee0529a11e431e47df67b703d4d8fa", + "sha256:b7c6ddfca2b141b0385387cc56c125b14ea867902c39e3fc650ddd6c429b17da", + "sha256:ffbb927679b62fad5071439d5fe0840af46ad1844bc44bf80e1a0ad706140c98" + ], + "markers": "python_version >= '3.8'", + "version": "==1.36.0" + }, + "pluggy": { + "hashes": [ + "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", + "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.0" + }, "prometheus-client": { "hashes": [ "sha256:21e674f39831ae3f8acde238afd9a27a37d0d2fb5a28ea094f0ce25d2cbf2091", @@ -848,6 +885,13 @@ ], "version": "==2.21" }, + "pyee": { + "hashes": [ + "sha256:2770c4928abc721f46b705e6a72b0c59480c4a69c9a83ca0b00bb994f1ea4b32", + "sha256:9f066570130c554e9cc12de5a9d86f57c7ee47fece163bbdaa3e9c933cfbdfa5" + ], + "version": "==9.0.4" + }, "pyexcel": { "hashes": [ "sha256:ddc6904512bfa2ecda509fb3b58229bb30db14498632fd9e7a5ba7bbfb02ed1b", @@ -942,6 +986,30 @@ "index": "pypi", "version": "==3.6.0" }, + "pytest": { + "hashes": [ + "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", + "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" + ], + "markers": "python_version >= '3.7'", + "version": "==7.4.0" + }, + "pytest-base-url": { + "hashes": [ + "sha256:e1e88a4fd221941572ccdcf3bf6c051392d2f8b6cef3e0bc7da95abec4b5346e", + "sha256:ed36fd632c32af9f1c08f2c2835dcf42ca8fcd097d6ed44a09f253d365ad8297" + ], + "markers": "python_version >= '3.7' and python_version < '4.0'", + "version": "==2.0.0" + }, + "pytest-playwright": { + "hashes": [ + "sha256:83a896b1b28bfaa081ca9ea27229a06a114e106e2e62fb3d5f06544748fbc1fe", + "sha256:9bf79c633c97dd1405308b8d3600e6c8c2a200a733e2f36c5a150ba4701936f8" + ], + "index": "pypi", + "version": "==0.3.3" + }, "python-dateutil": { "hashes": [ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", @@ -966,6 +1034,14 @@ "markers": "python_version >= '3.6'", "version": "==2.0.7" }, + "python-slugify": { + "hashes": [ + "sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395", + "sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27" + ], + "markers": "python_version >= '3.7'", + "version": "==8.0.1" + }, "pytz": { "hashes": [ "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", @@ -1118,6 +1194,13 @@ ], "version": "==2.0.1" }, + "text-unidecode": { + "hashes": [ + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + ], + "version": "==1.3" + }, "texttable": { "hashes": [ "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2", @@ -1125,6 +1208,14 @@ ], "version": "==1.6.7" }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version < '3.11'", + "version": "==2.0.1" + }, "typing-extensions": { "hashes": [ "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", @@ -1215,19 +1306,19 @@ }, "boto3": { "hashes": [ - "sha256:0fe7a35cf0041145c8eefebd3ae2ddf41baed62d7c963e5042b8ed8c297f648f", - "sha256:e24460d50001b517c6734dcf1c879feb43aa2062d88d9bdbb8703c986cb05941" + "sha256:b2d178c8a56fe3e4c9b123dccdff20e9555d12a597b72627fa659aa6295e238a", + "sha256:db6443fd2c65d9f35f671b03bacb0592b62d06884395ed65d75922ccddc34c2e" ], "markers": "python_version >= '3.7'", - "version": "==1.28.11" + "version": "==1.28.13" }, "botocore": { "hashes": [ - "sha256:b17ff973bb70b02b227928c2abe4992f1cfc46d13aee0228516c8f32572b88c6", - "sha256:d3cbffe554c9a1ba2ac6973734c43c21b8e7985a2ac4a4c31a09811b8029445c" + "sha256:78b96afbd88b8bd4c0967611a4cedddd9ea33d8601309dc351f81cbb5479d976", + "sha256:9a5080ea2a444f0447a7a1a79f64252ae2a1417b6c13a54656ee991cb610dd4e" ], "markers": "python_version >= '3.7'", - "version": "==1.31.11" + "version": "==1.31.13" }, "cachecontrol": { "extras": [ @@ -1476,11 +1567,11 @@ }, "flake8-bugbear": { "hashes": [ - "sha256:beb5c7efcd7ccc2039ef66a77bb8db925e7be3531ff1cb4d0b7030d0e2113d72", - "sha256:e3e7f74c8a49ad3794a7183353026dabd68c74030d5f46571f84c1fb0eb79363" + "sha256:0ebdc7d8ec1ca8bd49347694562381f099f4de2f8ec6bda7a7dca65555d9e0d4", + "sha256:d99d005114020fbef47ed5e4aebafd22f167f9a0fbd0d8bf3c9e90612cb25c34" ], "index": "pypi", - "version": "==23.3.12" + "version": "==23.7.10" }, "flake8-print": { "hashes": [ @@ -1845,7 +1936,7 @@ "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" ], - "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==7.4.0" }, "pytest-env": { diff --git a/README.md b/README.md index bbb298684..202b69e17 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ The [Notify API](https://github.com/GSA/notifications-api) provides the UI's bac ### Common steps -1. Install pre-requisites for setup: +1. Install pre-requisites for setup (on a Mac): + - Install XCode or at least the XCode Command Line Tools + - [Homebrew](https://brew.sh/) (follow instructions on page) - [jq](https://stedolan.github.io/jq/): `brew install jq` - [terraform](https://www.terraform.io/): `brew install terraform` or `brew install tfenv` and use `tfenv` to install `terraform ~> 1.4.0` - [cf-cli@8](https://docs.cloudfoundry.org/cf-cli/install-go-cli.html): `brew install cloudfoundry/tap/cf-cli@8` @@ -44,6 +46,23 @@ The [Notify API](https://github.com/GSA/notifications-api) provides the UI's bac `make bootstrap` + If you run into certificate errors at the `playwright install` step, try doing this: + + 1. Run `brew --prefix` to see Homebrew's root directory + + 1. Create or modify the local `.env` file in the project and add this line: + + `NODE_EXTRA_CA_CERTS=/CHANGE-TO-HOMEBREW-INSTALL-PATH/etc/ca-certificates/cert.pem` + + Make sure to change `CHANGE-TO-HOMEBREW-INSTALL-PATH` to the path given by `brew --prefix` in the step above. + For example, if `brew --prefix` gave `/opt/homebrew` as output, then the line would look like this: + + `NODE_EXTRA_CA_CERTS=/opt/homebrew/etc/ca-certificates/cert.pem` + + 1. Save the changes to the `.env` file + + 1. Run `make bootstrap` again + 1. Run the Flask server `make run-flask` diff --git a/app/assets/error_pages/5xx.html b/app/assets/error_pages/5xx.html index a6bf68571..fcf9db915 100644 --- a/app/assets/error_pages/5xx.html +++ b/app/assets/error_pages/5xx.html @@ -4,7 +4,7 @@ - Sorry, there is a problem with the service – U.S. Notify + Sorry, there is a problem with the service – Notify.gov diff --git a/app/assets/images/product/01-templates-no-chrome.svg b/app/assets/images/product/01-templates-no-chrome.svg index ceadfd829..1f5bf9ad0 100644 --- a/app/assets/images/product/01-templates-no-chrome.svg +++ b/app/assets/images/product/01-templates-no-chrome.svg @@ -1,4 +1,4 @@ - + @@ -69,8 +69,7 @@ - - + @@ -86,12 +85,8 @@ - - - - diff --git a/app/assets/images/product/02-reporting-no-chrome.svg b/app/assets/images/product/02-reporting-no-chrome.svg index d6ef5e90b..e82ec8303 100644 --- a/app/assets/images/product/02-reporting-no-chrome.svg +++ b/app/assets/images/product/02-reporting-no-chrome.svg @@ -1,4 +1,4 @@ - + @@ -69,8 +69,7 @@ - - + @@ -80,12 +79,8 @@ - - - - diff --git a/app/assets/images/product/03-spreadsheet-no-chrome.svg b/app/assets/images/product/03-spreadsheet-no-chrome.svg index 6c5a6f074..8580fa9ff 100644 --- a/app/assets/images/product/03-spreadsheet-no-chrome.svg +++ b/app/assets/images/product/03-spreadsheet-no-chrome.svg @@ -97,12 +97,11 @@ - - + - + @@ -110,16 +109,12 @@ - - - - + - - + diff --git a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss index 3a6a43dd0..ed7b9aa70 100644 --- a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss +++ b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss @@ -22,8 +22,9 @@ i.e. @use "uswds-core" as *; -.usa-logo { +.usa-header--extended .usa-logo { font-family: family("sans"); + margin: units(4) 0; img { @include at-media($theme-header-min-width) { width: 80px; diff --git a/app/formatters.py b/app/formatters.py index 49411ddbf..6525ead4b 100644 --- a/app/formatters.py +++ b/app/formatters.py @@ -34,14 +34,14 @@ def convert_to_boolean(value): def format_datetime(date): - return '{} at {}'.format( + return '{} at {} UTC'.format( format_date(date), format_time_24h(date) ) def format_datetime_24h(date): - return '{} at {}'.format( + return '{} at {} UTC'.format( format_date(date), format_time_24h(date), ) @@ -52,28 +52,28 @@ def format_time(date): def format_datetime_normal(date): - return '{} at {}'.format( + return '{} at {} UTC'.format( format_date_normal(date), format_time_24h(date) ) def format_datetime_short(date): - return '{} at {}'.format( + return '{} at {} UTC'.format( format_date_short(date), format_time_24h(date) ) def format_datetime_relative(date): - return '{} at {}'.format( + return '{} at {} UTC'.format( get_human_day(date), format_time_24h(date) ) def format_datetime_numeric(date): - return '{} {}'.format( + return '{} {} UTC'.format( format_date_numeric(date), format_time_24h(date), ) @@ -134,7 +134,7 @@ def format_date_human(date): def format_datetime_human(date, date_prefix=''): - return '{} at {}'.format( + return '{} at {} UTC'.format( get_human_day(date, date_prefix='on'), format_time_24h(date), ) diff --git a/app/main/views/add_service.py b/app/main/views/add_service.py index 88f498969..f42331f43 100644 --- a/app/main/views/add_service.py +++ b/app/main/views/add_service.py @@ -35,7 +35,7 @@ def _create_example_template(service_id): example_sms_template = service_api_client.create_service_template( 'Example text message template', 'sms', - 'Hi, I’m trying out U.S. Notify. Today is ((day of week)) and my favorite color is ((color)).', + 'Hi, I’m trying out Notify.gov. Today is ((day of week)) and my favorite color is ((color)).', service_id, ) return example_sms_template diff --git a/app/main/views/feedback.py b/app/main/views/feedback.py index ab0bd3328..d117affbe 100644 --- a/app/main/views/feedback.py +++ b/app/main/views/feedback.py @@ -76,7 +76,7 @@ def triage(ticket_type=PROBLEM_TICKET_TYPE): form=form, page_title={ PROBLEM_TICKET_TYPE: 'Report a problem', - GENERAL_TICKET_TYPE: 'Contact U.S. Notify support', + GENERAL_TICKET_TYPE: 'Contact Notify.gov support', }.get(ticket_type) ) @@ -151,7 +151,7 @@ def feedback(ticket_type): ), show_status_page_banner=(ticket_type == PROBLEM_TICKET_TYPE), page_title={ - GENERAL_TICKET_TYPE: 'Contact U.S. Notify support', + GENERAL_TICKET_TYPE: 'Contact Notify.gov support', PROBLEM_TICKET_TYPE: 'Report a problem', QUESTION_TICKET_TYPE: 'Ask a question or give feedback', }.get(ticket_type), diff --git a/app/navigation.py b/app/navigation.py index 625164392..d2af07e68 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -267,7 +267,6 @@ class OrgNavigation(Navigation): 'edit_organization_billing_details', 'edit_organization_domains', 'edit_organization_email_branding', - 'edit_organization_domains', 'edit_organization_go_live_notes', 'edit_organization_name', 'edit_organization_notes', diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index f56108e5c..703719a73 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -35,7 +35,7 @@ {% endblock %} {% block pageTitle %} - {% block per_page_title %}{% endblock %} – U.S. Notify + {% block per_page_title %}{% endblock %} – Notify.gov {% endblock %} {% block bodyStart %} diff --git a/app/templates/components/uk_components/header/template.njk b/app/templates/components/uk_components/header/template.njk index 6464705b1..439165036 100644 --- a/app/templates/components/uk_components/header/template.njk +++ b/app/templates/components/uk_components/header/template.njk @@ -60,13 +60,13 @@
diff --git a/app/templates/error/401.html b/app/templates/error/401.html index 64f9b155b..b579650dc 100644 --- a/app/templates/error/401.html +++ b/app/templates/error/401.html @@ -4,6 +4,6 @@

You’re not authorised to see this page

-

Sign in to U.S. Notify and try again.

+

Sign in to Notify.gov and try again.

{% endblock %} diff --git a/app/templates/error/500.html b/app/templates/error/500.html index 76890ce0e..db505a014 100644 --- a/app/templates/error/500.html +++ b/app/templates/error/500.html @@ -4,7 +4,7 @@

- Sorry, there’s a problem with U.S. Notify + Sorry, there’s a problem with Notify.gov

Try again later. diff --git a/app/templates/main_template.html b/app/templates/main_template.html index 54535b88d..51f0c2369 100644 --- a/app/templates/main_template.html +++ b/app/templates/main_template.html @@ -7,7 +7,7 @@ - {% block pageTitle %}U.S. Notify{% endblock %} + {% block pageTitle %}Notify.gov{% endblock %} {# Hardcoded value of $govuk-black #} {% if config['NR_MONITOR_ON'] %} diff --git a/app/templates/partials/jobs/status.html b/app/templates/partials/jobs/status.html index ce0245a6d..e826fc0cf 100644 --- a/app/templates/partials/jobs/status.html +++ b/app/templates/partials/jobs/status.html @@ -15,7 +15,7 @@ Notify cannot send these messages because you have reached a limit. You can only send {{ current_service.message_limit|format_thousands }} messages per day and {{ 250000|format_thousands }} messages in total.

- Upload this spreadsheet again tomorrow or contact the U.S. Notify team to raise the limit. + Upload this spreadsheet again tomorrow or contact the Notify.gov team to raise the limit.

{% endif %}
diff --git a/app/templates/views/accessibility_statement.html b/app/templates/views/accessibility_statement.html index 3b09eec3a..6cd07dc22 100644 --- a/app/templates/views/accessibility_statement.html +++ b/app/templates/views/accessibility_statement.html @@ -19,7 +19,7 @@ ) }}

- This accessibility statement applies to the U.S. Notify domain. + This accessibility statement applies to the Notify.gov domain.

@@ -66,7 +66,7 @@

Feedback and contact information

- If you need any part of this service in a different format like large print, audio recording or braille, contact the U.S. Notify team. + If you need any part of this service in a different format like large print, audio recording or braille, contact the Notify.gov team.

@@ -76,7 +76,7 @@

Reporting accessibility problems with this website

- We’re always looking to improve the accessibility of this website. If you find any problems not listed on this page or think we’re not meeting accessibility requirements, contact the U.S. Notify team. + We’re always looking to improve the accessibility of this website. If you find any problems not listed on this page or think we’re not meeting accessibility requirements, contact the Notify.gov team.

Technical information about this website’s accessibility

@@ -88,7 +88,7 @@

- U.S. Notify is partially compliant with the Web Content Accessibility Guidelines (WCAG) version 2.1 AA standard, due to the non-compliances listed below. + Notify.gov is partially compliant with the Web Content Accessibility Guidelines (WCAG) version 2.1 AA standard, due to the non-compliances listed below.

Non-accessible content

@@ -195,6 +195,6 @@

- We decided which pages to test based on the most common tasks that U.S. Notify users need to complete. We also tested a sample of pages with common user interface components. + We decided which pages to test based on the most common tasks that Notify.gov users need to complete. We also tested a sample of pages with common user interface components.

--> {% endblock %} diff --git a/app/templates/views/cookies.html b/app/templates/views/cookies.html index 1263b91e6..11f918c05 100644 --- a/app/templates/views/cookies.html +++ b/app/templates/views/cookies.html @@ -21,7 +21,7 @@

Cookies are small files saved on your phone, tablet, or computer when you visit a website.

-

We use cookies to make U.S. Notify work and collect information about how you use our service.

+

We use cookies to make Notify.gov work and collect information about how you use our service.

Essential cookies

@@ -73,7 +73,7 @@ Google Analytics stores anonymized information about:

    -
  • how you got to U.S. Notify
  • +
  • how you got to Notify.gov
  • the pages you visit on Notify and how long you spend on them
  • any errors you see while using Notify
diff --git a/app/templates/views/dashboard/_totals.html b/app/templates/views/dashboard/_totals.html index 6ea69e13f..62d4af437 100644 --- a/app/templates/views/dashboard/_totals.html +++ b/app/templates/views/dashboard/_totals.html @@ -2,7 +2,7 @@
-
+
{{ big_number_with_status( statistics['sms']['requested'], statistics['sms']['requested']|message_count_label('sms', suffix='sent'), @@ -14,7 +14,7 @@ smaller=True, ) }}
-
+
diff --git a/app/templates/views/dashboard/_usage.html b/app/templates/views/dashboard/_usage.html index 61dc279d7..34e63c496 100644 --- a/app/templates/views/dashboard/_usage.html +++ b/app/templates/views/dashboard/_usage.html @@ -1,7 +1,7 @@ {% from "components/big-number.html" import big_number %}
-
+
{% if sms_cost %} {{ big_number( @@ -15,9 +15,9 @@ {% endif %}
-
+
diff --git a/app/templates/views/documentation.html b/app/templates/views/documentation.html index 9ebb68219..e0ac1452b 100644 --- a/app/templates/views/documentation.html +++ b/app/templates/views/documentation.html @@ -7,7 +7,7 @@ {% block content_column_content %}

Documentation

-

This documentation is for developers who want to integrate the U.S. Notify API with a web application or back office system.

+

This documentation is for developers who want to integrate the Notify.gov API with a web application or back office system.

Client libraries

Links to documentation open in a new tab.

    diff --git a/app/templates/views/features.html b/app/templates/views/features.html index 1e03dd923..7c529d57d 100644 --- a/app/templates/views/features.html +++ b/app/templates/views/features.html @@ -10,7 +10,7 @@ {% block content_column_content %}

    Features

    -

    If you work for the government, you can use U.S. Notify to keep your users updated.

    +

    If you work for the government, you can use Notify.gov to keep your users updated.

    Notify makes it easy to create, customize, and send text messages.

    {% else %}

    Users will see your service name as your email sender name.

    {% endif %}
+

The service name you enter here will appear at the beginning of each text message, unless you turn off this off in Settings > Start text message with service name. + {% call form_wrapper() %} {{ form.name }} diff --git a/app/templates/views/service-settings/name.html b/app/templates/views/service-settings/name.html index 0bffb3b2d..6c0dc364f 100644 --- a/app/templates/views/service-settings/name.html +++ b/app/templates/views/service-settings/name.html @@ -22,17 +22,17 @@

You should only use an acronym or initialism if your users are already familiar with it.

-
+
{% if current_service.prefix_sms %} -

Users will see your service name:

-
    -
  • at the start of every text message
  • -
  • as your email sender name
  • -
+ +

Users will see your service name at the start of every text message

{% else %} -

Users will see your service name as your email sender name.

+

Users will see your service name as your email sender name.

{% endif %} +
+

The service name you enter here will appear at the beginning of each text message, unless you turn off this off in Settings > Start text message with service name. + {% call form_wrapper() %} {{ form.name }} diff --git a/app/templates/views/service-settings/set-email.html b/app/templates/views/service-settings/set-email.html index 56f777a34..215c15121 100644 --- a/app/templates/views/service-settings/set-email.html +++ b/app/templates/views/service-settings/set-email.html @@ -18,7 +18,7 @@

{{ page_header('Send emails') }}

- It’s free to send emails through U.S. Notify. + It’s free to send emails through Notify.gov.

{% call form_wrapper() %} {{ form.enabled }} diff --git a/app/templates/views/signedout.html b/app/templates/views/signedout.html index da841528f..2a924a566 100644 --- a/app/templates/views/signedout.html +++ b/app/templates/views/signedout.html @@ -12,10 +12,10 @@ Notify.gov {% block content %} -
-
+
+
-
+

Send text messages to your participants

Notify.gov is a text messaging service that helps federal, state, local, tribal, and territorial governments more effectively communicate with their program participants.

@@ -25,7 +25,7 @@ Notify.gov

Currently we are only working with select pilot partners. If you are interested in using Notify.gov in the future, please contact
tts-benefits-studio@gsa.gov to learn more.

-
+ @@ -34,13 +34,13 @@ Notify.gov
-
+

Control your content

You do not need any technical knowledge to create message templates.

-
+
Example screenshot of adding a new text message template
@@ -48,13 +48,13 @@ Notify.gov
-
+

See how your messages perform

Track how many messages you’ve sent and find out which ones are not being delivered.

-
+
A screenshot of Notify.gov showing counts of emails and text messages sent
@@ -62,13 +62,13 @@ Notify.gov
-
+

No technical integration needed

Upload a spreadsheet of phone numbers and Notify.gov sends batches of messages for you.

-
+
A screenshot of a spreadsheet with phone numbers, names, and a reference number
diff --git a/app/templates/views/support/form.html b/app/templates/views/support/form.html index 7d5a31415..27e5cf0aa 100644 --- a/app/templates/views/support/form.html +++ b/app/templates/views/support/form.html @@ -22,7 +22,7 @@

Check our system status - page to see if there are any known issues with U.S. Notify. + page to see if there are any known issues with Notify.gov.

{% endif %} diff --git a/app/templates/views/support/index.html b/app/templates/views/support/index.html index d2ac6fc6f..2311a04c0 100644 --- a/app/templates/views/support/index.html +++ b/app/templates/views/support/index.html @@ -14,7 +14,7 @@

You can expect a response within one business day.

- + +
#} {% if months %}
diff --git a/docs/end_to_end_tests.md b/docs/end_to_end_tests.md new file mode 100644 index 000000000..906200a1c --- /dev/null +++ b/docs/end_to_end_tests.md @@ -0,0 +1,120 @@ +# Working with End-to-End Tests + +End-to-End (E2E) tests are an important part of a assessing the overall +integrity and stability of a system. They are a part of the overall +test suite and serve the function of simulating a user working through +the application. By having comprehensive E2E tests in place, we can +instill higher confidence that future changes and refactorings won't +negatively impact any user experience or break existing functionality. + +The US Notify project leverages [`pytest`](https://pytest.org/) for its +existing test suite (at least on the Python side of things) and is now +leveraging [Playwright for Python](https://playwright.dev/python/) +along with its `pytest` plugin for the E2E tests. + + +## Getting Started + +To work with the E2E tests in US Notify, you need to make sure you have +all of the necessary components installed. The quick and easy way to do +this is to use the Makefile as you did for the initial project setup. In +fact, if you've already done this, you are already set to go! If not, +then run the bootstrap command in your shell: + +```sh +make bootstrap +``` + +This takes care of installing all of your dependencies, including those +now needed for Playwright. + +If you run into certificate errors at the `playwright install` step, try +doing this: + +1. Run `brew --prefix` to see Homebrew's root directory + +1. Create or modify the local `.env` file in the project and add this line: + + `NODE_EXTRA_CA_CERTS=/CHANGE-TO-HOMEBREW-INSTALL-PATH/etc/ca-certificates/cert.pem` + + Make sure to change `CHANGE-TO-HOMEBREW-INSTALL-PATH` to the path + given by `brew --prefix` in the step above. For example, if `brew --prefix` + gave `/opt/homebrew` as output, then the line would look like this: + + `NODE_EXTRA_CA_CERTS=/opt/homebrew/etc/ca-certificates/cert.pem` + +1. Save the changes to the `.env` file + +1. Run `make bootstrap` again + + +### Manual Installation + +If you need to install things separately, you'll still need to make sure +your environment is set up and configured as outlined in the README. + +At your shell in the project root folder, run the following commands: + +```sh +pipenv install pytest-playwright +pipenv run playwright install --with-deps +``` + +This will install Playwright and its `pytest` plugin, then the +additional dependencies that Playwright requires. + +See more details on the [Playwright for Python Installation page](https://playwright.dev/python/docs/intro). + + +## Local Configuration + +In order to run the E2E tests successfully on your local machine, you'll also +need to make sure you have a `.env` file in the root project folder, and that it +has at least these environment variables set in it: + +``` +NOTIFY_STAGING_URI +NOTIFY_STAGING_HTTP_AUTH_USER +NOTIFY_STAGING_HTTP_AUTH_PASSWORD +``` + +This file is **not** checked into source control and is configured to be +ignored in the project's `.gitignore` file; please be careful that it is +not committed to the repo and pushed! + + +## Running E2E Tests Locally + +To run the E2E tests on your local machine, type this command in your +shell at the project root directory: + +```sh +make e2e-test +``` + +You should see `pytest` start producing output and the existing E2E +tests run in multiple headless browsers. + + +## How to Create and Maintain E2E Tests + +All of the E2E tests are found in the `tests/end_to_end` folder and are +written as `pytest` scripts using [Playwright's Python Framework](https://playwright.dev/python/docs/writing-tests). + + +## Maintaining E2E Tests with GitHub + +The E2E tests are configured to run as a separate GitHub action as a +part of our other checks found in `.github/workflows/checks.yml`. + +The E2E tests are not run as a part of the regular unit test suite; if +you look at the `Makefile` you'll see that the tests are two separate +commands, with the E2E tests configured separately. + +This is done for a couple of reasons: + +- Keeps unit tests isolated from the E2E tests +- Allows us to configure E2E tests separately + +The environment variables are managed as a part of the GitHub +repository settings. diff --git a/paas-failwhale/index.html b/paas-failwhale/index.html index 0b1fba71c..81622eb8b 100644 --- a/paas-failwhale/index.html +++ b/paas-failwhale/index.html @@ -4,7 +4,7 @@ - Sorry, the service is unavailable – U.S. Notify + Sorry, the service is unavailable – Notify.gov diff --git a/package-lock.json b/package-lock.json index 6656ccc6b..9f99b0ea1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15716,9 +15716,9 @@ "dev": true }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -28109,9 +28109,9 @@ "dev": true }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true }, "wrap-ansi": { diff --git a/tests/app/main/test_errorhandlers.py b/tests/app/main/test_errorhandlers.py index 8e8be0808..b6ec8c927 100644 --- a/tests/app/main/test_errorhandlers.py +++ b/tests/app/main/test_errorhandlers.py @@ -10,7 +10,7 @@ def test_bad_url_returns_page_not_found(client_request): _expected_status=404, ) assert page.h1.string.strip() == 'Page not found' - assert page.title.string.strip() == 'Page not found – U.S. Notify' + assert page.title.string.strip() == 'Page not found – Notify.gov' def test_load_service_before_request_handles_404(client_request, mocker): @@ -37,7 +37,7 @@ def test_malformed_token_returns_page_not_found(client_request, url): assert page.h1.string.strip() == 'Page not found' flash_banner = page.find('div', class_='banner-dangerous').string.strip() assert flash_banner == "There’s something wrong with the link you’ve used." - assert page.title.string.strip() == 'Page not found – U.S. Notify' + assert page.title.string.strip() == 'Page not found – Notify.gov' def test_csrf_returns_400(client_request, mocker): @@ -51,8 +51,8 @@ def test_csrf_returns_400(client_request, mocker): _test_page_title=False, ) - assert page.h1.string.strip() == 'Sorry, there’s a problem with U.S. Notify' - assert page.title.string.strip() == 'Sorry, there’s a problem with the service – U.S. Notify' + assert page.h1.string.strip() == 'Sorry, there’s a problem with Notify.gov' + assert page.title.string.strip() == 'Sorry, there’s a problem with the service – Notify.gov' def test_csrf_redirects_to_sign_in_page_if_not_signed_in(client_request, mocker): @@ -69,5 +69,5 @@ def test_csrf_redirects_to_sign_in_page_if_not_signed_in(client_request, mocker) def test_405_returns_something_went_wrong_page(client_request, mocker): page = client_request.post_url('/', _expected_status=405) - assert page.h1.string.strip() == 'Sorry, there’s a problem with U.S. Notify' - assert page.title.string.strip() == 'Sorry, there’s a problem with the service – U.S. Notify' + assert page.h1.string.strip() == 'Sorry, there’s a problem with Notify.gov' + assert page.title.string.strip() == 'Sorry, there’s a problem with the service – Notify.gov' diff --git a/tests/app/main/test_formatters.py b/tests/app/main/test_formatters.py index 946b05cbc..89d8016da 100644 --- a/tests/app/main/test_formatters.py +++ b/tests/app/main/test_formatters.py @@ -57,38 +57,38 @@ def test_format_number_in_pounds_as_currency(input_number, formatted_number): @pytest.mark.parametrize('time, human_readable_datetime', [ # incoming in UTC, outgoing in "human formatted" UTC - ('2018-03-14 09:00', '14 March at 09:00'), - ('2018-03-14 19:00', '14 March at 19:00'), + ('2018-03-14 09:00', '14 March at 09:00 UTC'), + ('2018-03-14 19:00', '14 March at 19:00 UTC'), - ('2018-03-15 09:00', '15 March at 09:00'), - ('2018-03-15 19:00', '15 March at 19:00'), + ('2018-03-15 09:00', '15 March at 09:00 UTC'), + ('2018-03-15 19:00', '15 March at 19:00 UTC'), - ('2018-03-19 09:00', '19 March at 09:00'), - ('2018-03-19 19:00', '19 March at 19:00'), - ('2018-03-19 23:59', '19 March at 23:59'), + ('2018-03-19 09:00', '19 March at 09:00 UTC'), + ('2018-03-19 19:00', '19 March at 19:00 UTC'), + ('2018-03-19 23:59', '19 March at 23:59 UTC'), - ('2018-03-20 00:00', '19 March at 00:00'), # we specifically refer to 00:00 as belonging to the day before. - ('2018-03-20 04:01', 'yesterday at 04:01'), - ('2018-03-20 09:00', 'yesterday at 09:00'), - ('2018-03-20 19:00', 'yesterday at 19:00'), - ('2018-03-20 23:59', 'yesterday at 23:59'), + ('2018-03-20 00:00', '19 March at 00:00 UTC'), # we specifically refer to 00:00 as belonging to the day before. + ('2018-03-20 04:01', 'yesterday at 04:01 UTC'), + ('2018-03-20 09:00', 'yesterday at 09:00 UTC'), + ('2018-03-20 19:00', 'yesterday at 19:00 UTC'), + ('2018-03-20 23:59', 'yesterday at 23:59 UTC'), - ('2018-03-21 00:00', 'yesterday at 00:00'), # we specifically refer to 00:00 as belonging to the day before. - ('2018-03-21 04:01', 'today at 04:01'), - ('2018-03-21 09:00', 'today at 09:00'), - ('2018-03-21 12:00', 'today at 12:00'), - ('2018-03-21 19:00', 'today at 19:00'), - ('2018-03-21 23:59', 'today at 23:59'), + ('2018-03-21 00:00', 'yesterday at 00:00 UTC'), # we specifically refer to 00:00 as belonging to the day before. + ('2018-03-21 04:01', 'today at 04:01 UTC'), + ('2018-03-21 09:00', 'today at 09:00 UTC'), + ('2018-03-21 12:00', 'today at 12:00 UTC'), + ('2018-03-21 19:00', 'today at 19:00 UTC'), + ('2018-03-21 23:59', 'today at 23:59 UTC'), - ('2018-03-22 00:00', 'today at 00:00'), - ('2018-03-22 04:01', 'tomorrow at 04:01'), - ('2018-03-22 09:00', 'tomorrow at 09:00'), - ('2018-03-22 19:00', 'tomorrow at 19:00'), - ('2018-03-22 23:59', 'tomorrow at 23:59'), + ('2018-03-22 00:00', 'today at 00:00 UTC'), + ('2018-03-22 04:01', 'tomorrow at 04:01 UTC'), + ('2018-03-22 09:00', 'tomorrow at 09:00 UTC'), + ('2018-03-22 19:00', 'tomorrow at 19:00 UTC'), + ('2018-03-22 23:59', 'tomorrow at 23:59 UTC'), - ('2018-03-23 04:01', '23 March at 04:01'), - ('2018-03-23 09:00', '23 March at 09:00'), - ('2018-03-23 19:00', '23 March at 19:00'), + ('2018-03-23 04:01', '23 March at 04:01 UTC'), + ('2018-03-23 09:00', '23 March at 09:00 UTC'), + ('2018-03-23 19:00', '23 March at 19:00 UTC'), ]) def test_format_datetime_relative(time, human_readable_datetime): diff --git a/tests/app/main/views/organizations/test_organizations.py b/tests/app/main/views/organizations/test_organizations.py index a8075101c..f4ac2944f 100644 --- a/tests/app/main/views/organizations/test_organizations.py +++ b/tests/app/main/views/organizations/test_organizations.py @@ -85,7 +85,7 @@ def test_view_organization_shows_the_correct_organization( assert normalize_spaces(page.select_one('h1').text) == 'Usage' assert normalize_spaces(page.select_one('.govuk-hint').text) == ( - 'Test 1 has no live services on U.S. Notify' + 'Test 1 has no live services on Notify.gov' ) assert not page.select('a[download]') diff --git a/tests/app/main/views/service_settings/test_service_settings.py b/tests/app/main/views/service_settings/test_service_settings.py index 1df4bba24..d14fbadf6 100644 --- a/tests/app/main/views/service_settings/test_service_settings.py +++ b/tests/app/main/views/service_settings/test_service_settings.py @@ -57,7 +57,6 @@ def mock_get_service_settings_page_common( 'Service name Test Service Change service name', 'Sign-in method Text message code Change sign-in method', 'Send text messages On Change your settings for sending text messages', - 'Text message senders GOVUK Manage text message senders', 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages Off Change your settings for sending international text messages', @@ -68,7 +67,7 @@ def mock_get_service_settings_page_common( 'Service name Test Service Change service name', 'Sign-in method Text message code Change sign-in method', 'Send text messages On Change your settings for sending text messages', - 'Text message senders GOVUK Manage text message senders', + 'Text message senders (Only visible to Platform Admins) GOVUK Manage text message senders', 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages Off Change your settings for sending international text messages', @@ -111,7 +110,6 @@ def test_should_show_overview( page = client_request.get( 'main.service_settings', service_id=SERVICE_ONE_ID ) - assert page.find('h1').text == 'Settings' rows = page.select('tr') assert len(rows) == len(expected_rows) @@ -205,7 +203,6 @@ def test_send_files_by_email_row_on_settings_page( 'Service name service one Change service name', 'Sign-in method Text message code Change sign-in method', 'Send text messages On Change your settings for sending text messages', - 'Text message senders GOVUK Manage text message senders', 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages On Change your settings for sending international text messages', @@ -216,7 +213,6 @@ def test_send_files_by_email_row_on_settings_page( 'Service name service one Change service name', 'Sign-in method Email link or text message code Change sign-in method', 'Send text messages On Change your settings for sending text messages', - 'Text message senders GOVUK Manage text message senders', 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages Off Change your settings for sending international text messages', @@ -254,10 +250,9 @@ def test_should_show_service_name( assert page.select_one( 'main .govuk-body' ).text == 'Your service name should tell users what the message is about as well as who it’s from.' - assert normalize_spaces(page.select_one('main ul').text) == ( - 'at the start of every text message ' - 'as your email sender name' - ) + + assert "The service name you enter here will appear at the beginning of each text message, unless" in page.text + app.service_api_client.get_service.assert_called_with(SERVICE_ONE_ID) @@ -3072,7 +3067,7 @@ def test_unknown_channel_404s( ), ( 'email', - 'It’s free to send emails through U.S. Notify.', + 'It’s free to send emails through Notify.gov.', 'Send emails', [], 'False', @@ -3081,7 +3076,7 @@ def test_unknown_channel_404s( ), ( 'email', - 'It’s free to send emails through U.S. Notify.', + 'It’s free to send emails through Notify.gov.', 'Send emails', ['email', 'sms'], 'True', diff --git a/tests/app/main/views/test_activity.py b/tests/app/main/views/test_activity.py index a576ba3da..cdf1a5939 100644 --- a/tests/app/main/views/test_activity.py +++ b/tests/app/main/views/test_activity.py @@ -153,7 +153,7 @@ def test_can_show_notifications( assert normalize_spaces( first_row.select_one('.table-field-right-aligned .align-with-message-body').text ) == ( - 'Delivered 1 January at 06:01' + 'Delivered 1 January at 06:01 UTC' ) assert page_title in page.h1.text.strip() @@ -626,16 +626,16 @@ def test_redacts_templates_that_should_be_redacted( @freeze_time("2017-09-27 12:30:00.000000") @pytest.mark.parametrize( "message_type, status, expected_hint_status, single_line", [ - ('email', 'created', 'Sending since 27 September at 12:30', True), - ('email', 'sending', 'Sending since 27 September at 12:30', True), - ('email', 'temporary-failure', 'Inbox not accepting messages right now 27 September at 12:31', False), - ('email', 'permanent-failure', 'Email address does not exist 27 September at 12:31', False), - ('email', 'delivered', 'Delivered 27 September at 12:31', True), - ('sms', 'created', 'Sending since 27 September at 12:30', True), - ('sms', 'sending', 'Sending since 27 September at 12:30', True), - ('sms', 'temporary-failure', 'Phone not accepting messages right now 27 September at 12:31', False), - ('sms', 'permanent-failure', 'Not delivered 27 September at 12:31', False), - ('sms', 'delivered', 'Delivered 27 September at 12:31', True), + ('email', 'created', 'Sending since 27 September at 12:30 UTC', True), + ('email', 'sending', 'Sending since 27 September at 12:30 UTC', True), + ('email', 'temporary-failure', 'Inbox not accepting messages right now 27 September at 12:31 UTC', False), + ('email', 'permanent-failure', 'Email address does not exist 27 September at 12:31 UTC', False), + ('email', 'delivered', 'Delivered 27 September at 12:31 UTC', True), + ('sms', 'created', 'Sending since 27 September at 12:30 UTC', True), + ('sms', 'sending', 'Sending since 27 September at 12:30 UTC', True), + ('sms', 'temporary-failure', 'Phone not accepting messages right now 27 September at 12:31 UTC', False), + ('sms', 'permanent-failure', 'Not delivered 27 September at 12:31 UTC', False), + ('sms', 'delivered', 'Delivered 27 September at 12:31 UTC', True), ] ) def test_sending_status_hint_displays_correctly_on_notifications_page( diff --git a/tests/app/main/views/test_add_service.py b/tests/app/main/views/test_add_service.py index 06539a654..25dcc0c80 100644 --- a/tests/app/main/views/test_add_service.py +++ b/tests/app/main/views/test_add_service.py @@ -141,7 +141,7 @@ def test_should_add_service_and_redirect_to_tour_when_no_services( 'Example text message template', 'sms', ( - "Hi, I’m trying out U.S. Notify. Today is " + "Hi, I’m trying out Notify.gov. Today is " "((day of week)) and my favorite color is ((color))." ), 101, diff --git a/tests/app/main/views/test_conversation.py b/tests/app/main/views/test_conversation.py index 04c3738ce..f16abc242 100644 --- a/tests/app/main/views/test_conversation.py +++ b/tests/app/main/views/test_conversation.py @@ -99,7 +99,7 @@ def test_view_conversation( ) assert normalize_spaces(page.select_one('title').text) == ( - 'Received text message – service one – U.S. Notify' + 'Received text message – service one – Notify.gov' ) assert normalize_spaces(page.select_one('h1').text) == ( '2021234567' @@ -114,55 +114,55 @@ def test_view_conversation( for index, expected in enumerate([ ( 'message-8', - 'yesterday at 14:59', + 'yesterday at 14:59 UTC', ), ( 'message-7', - 'yesterday at 14:59', + 'yesterday at 14:59 UTC', ), ( 'message-6', - 'yesterday at 16:59', + 'yesterday at 16:59 UTC', ), ( 'message-5', - 'yesterday at 18:59', + 'yesterday at 18:59 UTC', ), ( 'message-4', - 'yesterday at 20:59', + 'yesterday at 20:59 UTC', ), ( 'message-3', - 'yesterday at 22:59', + 'yesterday at 22:59 UTC', ), ( 'message-2', - 'yesterday at 22:59', + 'yesterday at 22:59 UTC', ), ( 'message-1', - 'yesterday at 23:00', + 'yesterday at 23:00 UTC', ), ( expected_outbound_content, - 'yesterday at 00:00', + 'yesterday at 00:00 UTC', ), ( expected_outbound_content, - 'yesterday at 00:00', + 'yesterday at 00:00 UTC', ), ( expected_outbound_content, - 'yesterday at 00:00', + 'yesterday at 00:00 UTC', ), ( expected_outbound_content, - 'yesterday at 00:00', + 'yesterday at 00:00 UTC', ), ( expected_outbound_content, - 'yesterday at 00:00', + 'yesterday at 00:00 UTC', ), ]): assert ( diff --git a/tests/app/main/views/test_dashboard.py b/tests/app/main/views/test_dashboard.py index 142db9a94..beb7c87e9 100644 --- a/tests/app/main/views/test_dashboard.py +++ b/tests/app/main/views/test_dashboard.py @@ -389,14 +389,14 @@ def test_download_inbox( ) assert response.get_data(as_text=True) == ( 'Phone number,Message,Received\r\n' - '(202) 867-5300,message-1,2016-07-01 11:00\r\n' - '(202) 867-5300,message-2,2016-07-01 10:59\r\n' - '(202) 867-5300,message-3,2016-07-01 10:59\r\n' - '(202) 867-5302,message-4,2016-07-01 08:59\r\n' - '+33 1 12 34 56 78,message-5,2016-07-01 06:59\r\n' - '(202) 555-0104,message-6,2016-07-01 04:59\r\n' - '(202) 555-0104,message-7,2016-07-01 02:59\r\n' - '+682 12345,message-8,2016-07-01 02:59\r\n' + '(202) 867-5300,message-1,2016-07-01 11:00 UTC\r\n' + '(202) 867-5300,message-2,2016-07-01 10:59 UTC\r\n' + '(202) 867-5300,message-3,2016-07-01 10:59 UTC\r\n' + '(202) 867-5302,message-4,2016-07-01 08:59 UTC\r\n' + '+33 1 12 34 56 78,message-5,2016-07-01 06:59 UTC\r\n' + '(202) 555-0104,message-6,2016-07-01 04:59 UTC\r\n' + '(202) 555-0104,message-7,2016-07-01 02:59 UTC\r\n' + '+682 12345,message-8,2016-07-01 02:59 UTC\r\n' ) @@ -648,7 +648,7 @@ def test_should_show_upcoming_jobs_on_dashboard( page.select_one('a.banner-dashboard').text ) == ( '2 files waiting to send ' - 'sending starts today at 11:09' + 'sending starts today at 11:09 UTC' ) assert page.select_one('a.banner-dashboard')['href'] == url_for( @@ -746,12 +746,12 @@ def test_correct_font_size_for_big_numbers( ) assert ( - len(page.select_one('[data-key=totals]').select('.grid-col-6')) - ) == ( - len(page.select_one('[data-key=usage]').select('.grid-col-6')) + len(page.select_one('[data-key=totals]').select('.grid-col-12')) ) == ( + # len(page.select_one('[data-key=usage]').select('.grid-col-6')) + # ) == ( len(page.select('.big-number-with-status .big-number-smaller')) - ) == 2 + ) == 1 def test_should_not_show_jobs_on_dashboard_for_users_with_uploads_page( @@ -804,14 +804,13 @@ def test_usage_page( assert normalize_spaces(unselected_nav_links[1].text) == '2009 to 2010 fiscal year' annual_usage = page.find_all('div', {'class': 'govuk-grid-column-one-half'}) - # print(annual_usage) # annual stats are shown in two rows, each with three column; email is col 1 # email_column = normalize_spaces(annual_usage[0].text + annual_usage[2].text) # assert 'Emails' in email_column # assert '1,000 sent' in email_column - sms_column = normalize_spaces(annual_usage[0].text + annual_usage[1].text) + sms_column = normalize_spaces(annual_usage[0].text) assert 'Text messages' in sms_column assert '251,800 sent' in sms_column assert '250,000 free allowance' in sms_column @@ -845,8 +844,9 @@ def test_usage_page_no_sms_spend( ) annual_usage = page.find_all('div', {'class': 'govuk-grid-column-one-half'}) - sms_column = normalize_spaces(annual_usage[0].text + annual_usage[1].text) + sms_column = normalize_spaces(annual_usage[0].text) assert 'Text messages' in sms_column + assert '1,000 sent' in sms_column assert '250,000 free allowance' in sms_column assert '249,000 free allowance remaining' in sms_column assert '$0.00 spent' not in sms_column @@ -879,7 +879,7 @@ def test_usage_page_monthly_breakdown( assert '1,230 text messages at 1.70p' in monthly_breakdown -@pytest.mark.parametrize( +@ pytest.mark.parametrize( 'now, expected_number_of_months', [ (freeze_time("2017-03-31 11:09:00.061258"), 6), (freeze_time("2017-01-01 11:09:00.061258"), 4) @@ -954,7 +954,7 @@ def test_usage_page_for_invalid_year( ) -@freeze_time("2012-03-31 12:12:12") +@ freeze_time("2012-03-31 12:12:12") def test_future_usage_page( client_request, mock_get_annual_usage_for_service_in_future, @@ -1199,7 +1199,7 @@ def test_get_dashboard_totals_adds_percentages(): assert get_dashboard_totals(stats)['email']['failed_percentage'] == '0' -@pytest.mark.parametrize( +@ pytest.mark.parametrize( 'failures,expected', [ (2, False), (3, False), @@ -1253,7 +1253,7 @@ def _stats(requested, delivered, failed): return {'requested': requested, 'delivered': delivered, 'failed': failed} -@pytest.mark.parametrize('dict_in, expected_failed, expected_requested', [ +@ pytest.mark.parametrize('dict_in, expected_failed, expected_requested', [ ( {}, 0, @@ -1433,7 +1433,7 @@ def test_breadcrumb_shows_if_service_is_suspended( assert 'Suspended' in page.select_one('.navigation-service-name').text -@pytest.mark.parametrize('permissions', ( +@ pytest.mark.parametrize('permissions', ( ['email', 'sms'], )) def test_service_dashboard_shows_usage( @@ -1453,9 +1453,10 @@ def test_service_dashboard_shows_usage( page.select_one('[data-key=usage]').text ) == ( '$29.85 ' - 'spent on text messages ' - '0 ' - 'email disabled during SMS pilot' + 'spent on text messages' + # Disabled for pilot + # '0 ' + # 'email disabled during SMS pilot' ) diff --git a/tests/app/main/views/test_feedback.py b/tests/app/main/views/test_feedback.py index 6b087a5da..4f2f1ee4d 100644 --- a/tests/app/main/views/test_feedback.py +++ b/tests/app/main/views/test_feedback.py @@ -102,7 +102,7 @@ def test_get_support_as_someone_in_the_public_sector( _follow_redirects=True, ) assert normalize_spaces(page.select('h1')) == ( - 'Contact U.S. Notify support' + 'Contact Notify.gov support' ) assert page.select_one('form textarea[name=feedback]') assert page.select_one('form input[name=name]') @@ -120,7 +120,7 @@ def test_get_support_as_member_of_public( _follow_redirects=True, ) assert normalize_spaces(page.select('h1')) == ( - 'The U.S. Notify service is for people who work in the government' + 'The Notify.gov service is for people who work in the government' ) assert len(page.select('h2 a')) == 3 assert not page.select('form') @@ -410,7 +410,7 @@ def test_redirects_to_triage( @pytest.mark.parametrize('ticket_type, expected_h1', ( (PROBLEM_TICKET_TYPE, 'Report a problem'), - (GENERAL_TICKET_TYPE, 'Contact U.S. Notify support'), + (GENERAL_TICKET_TYPE, 'Contact Notify.gov support'), )) def test_options_on_triage_page( client_request, diff --git a/tests/app/main/views/test_index.py b/tests/app/main/views/test_index.py index c42bc7f4f..771db8bc9 100644 --- a/tests/app/main/views/test_index.py +++ b/tests/app/main/views/test_index.py @@ -30,7 +30,7 @@ def test_non_logged_in_user_can_see_homepage( # This area is hidden for the pilot # assert normalize_spaces(page.select_one('#whos-using-notify').text) == ( - # 'Who’s using U.S. Notify ' # Hiding this next area for the pilot + # 'Who’s using Notify.gov ' # Hiding this next area for the pilot # # Hiding this next area for the pilot # # 'See the list of services and organizations. ' # 'There are 111 Organizations and 9,999 Services using Notify.' @@ -225,7 +225,7 @@ def test_old_using_notify_page(client_request): def test_terms_page_has_correct_content(client_request): terms_page = client_request.get('main.terms') assert normalize_spaces(terms_page.select('main p')[0].text) == ( - 'These terms apply to your service’s use of U.S. Notify. ' + 'These terms apply to your service’s use of Notify.gov. ' 'You must be the service manager to accept them.' ) @@ -243,14 +243,14 @@ def test_css_is_served_from_correct_path(client_request): 'https://static.example.com/css/styles.css?', ][index]) +# Commenting out until after the pilot when we'll decide on a logo +# def test_resources_that_use_asset_path_variable_have_correct_path(client_request): -def test_resources_that_use_asset_path_variable_have_correct_path(client_request): +# page = client_request.get('main.documentation') # easy static page - page = client_request.get('main.documentation') # easy static page +# logo_svg_fallback = page.select_one('.usa-flag-logo') - logo_svg_fallback = page.select_one('.usa-flag-logo') - - assert logo_svg_fallback['src'].startswith('https://static.example.com/images/us-notify-color.png') +# assert logo_svg_fallback['src'].startswith('https://static.example.com/images/us-notify-color.png') @pytest.mark.parametrize('extra_args, email_branding_retrieved', ( diff --git a/tests/app/main/views/test_jobs.py b/tests/app/main/views/test_jobs.py index 5a017f8c9..81bc70aa0 100644 --- a/tests/app/main/views/test_jobs.py +++ b/tests/app/main/views/test_jobs.py @@ -83,7 +83,7 @@ def test_should_show_page_for_one_job( assert page.h1.text.strip() == 'thisisatest.csv' assert ' '.join(page.find('tbody').find('tr').text.split()) == ( - '2021234567 template content Delivered 1 January at 11:10' + '2021234567 template content Delivered 1 January at 11:10 UTC' ) assert page.find('div', {'data-key': 'notifications'})['data-resource'] == url_for( 'main.view_job_updates', @@ -104,7 +104,7 @@ def test_should_show_page_for_one_job( assert normalize_spaces(page.select_one('tbody tr').text) == normalize_spaces( '2021234567 ' 'template content ' - 'Delivered 1 January at 11:10' + 'Delivered 1 January at 11:10 UTC' ) assert page.select_one('tbody tr a')['href'] == url_for( 'main.view_notification', @@ -233,7 +233,7 @@ def test_should_show_job_with_sending_limit_exceeded_status( "Notify cannot send these messages because you have reached a limit. You can only send 1,000 messages per day and 250,000 messages in total." # noqa ) assert normalize_spaces(page.select('main p')[2].text) == ( - "Upload this spreadsheet again tomorrow or contact the U.S. Notify team to raise the limit." + "Upload this spreadsheet again tomorrow or contact the Notify.gov team to raise the limit." ) @@ -245,11 +245,11 @@ def test_should_show_job_with_sending_limit_exceeded_status( )), # Just started (datetime(2020, 1, 10, 0, 0, 0), datetime(2020, 1, 10, 0, 0, 1), ( - 'No messages to show yet…' + 'No messages to show yet…' )), # Created a while ago, just started (datetime(2020, 1, 1, 0, 0, 0), datetime(2020, 1, 10, 0, 0, 1), ( - 'No messages to show yet…' + 'No messages to show yet…' )), # Created a while ago, started just within the last 24h # TODO -- fails locally, should pass, tech debt due to timezone changes, re-evaluate after UTC changes @@ -329,7 +329,7 @@ def test_should_show_scheduled_job( ) assert normalize_spaces(page.select('main p')[1].text) == ( - 'Sending Two week reminder tomorrow at 05:00' + 'Sending Two week reminder tomorrow at 05:00 UTC' ) assert page.select('main p a')[0]['href'] == url_for( 'main.view_template_version', diff --git a/tests/app/main/views/test_providers.py b/tests/app/main/views/test_providers.py index cd04854ce..af36aaad8 100644 --- a/tests/app/main/views/test_providers.py +++ b/tests/app/main/views/test_providers.py @@ -188,7 +188,7 @@ def test_view_providers_shows_all_providers( assert table_data[1].text.strip() == "20" assert table_data[2].text.strip() == "42" assert table_data[3].text.strip() == "True" - assert table_data[4].text.strip() == "16 January at 15:20" + assert table_data[4].text.strip() == "16 January at 15:20 UTC" assert table_data[5].text.strip() == "Test User" domestic_sms_second_row = domestic_sms_table.tbody.find_all('tr')[1] diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index d11a97659..6c9b18bcf 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -49,7 +49,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): ), [ ( - 'Templates – service one – U.S. Notify', + 'Templates – service one – Notify.gov', 'Templates', [], {}, @@ -101,7 +101,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'Templates – service one – U.S. Notify', + 'Templates – service one – Notify.gov', 'Templates', [], {'template_type': 'all'}, @@ -149,7 +149,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'Templates – service one – U.S. Notify', + 'Templates – service one – Notify.gov', 'Templates', [], {'template_type': 'sms'}, @@ -184,7 +184,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'folder_one – Templates – service one – U.S. Notify', + 'folder_one – Templates – service one – Notify.gov', 'Templates folder_one', [{'template_type': 'all'}], {'template_folder_id': PARENT_FOLDER_ID}, @@ -212,7 +212,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'folder_one – Templates – service one – U.S. Notify', + 'folder_one – Templates – service one – Notify.gov', 'Templates folder_one', [{'template_type': 'sms'}], {'template_type': 'sms', 'template_folder_id': PARENT_FOLDER_ID}, @@ -237,7 +237,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'folder_one – Templates – service one – U.S. Notify', + 'folder_one – Templates – service one – Notify.gov', 'Templates folder_one', [{'template_type': 'email'}], {'template_type': 'email', 'template_folder_id': PARENT_FOLDER_ID}, @@ -248,7 +248,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): 'There are no email templates in this folder', ), ( - 'folder_one_one – folder_one – Templates – service one – U.S. Notify', + 'folder_one_one – folder_one – Templates – service one – Notify.gov', 'Templates folder_one folder_one_one', [ {'template_type': 'all'}, @@ -272,7 +272,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'folder_one_one_one – folder_one_one – folder_one – Templates – service one – U.S. Notify', + 'folder_one_one_one – folder_one_one – folder_one – Templates – service one – Notify.gov', 'Templates folder_one folder_one_one folder_one_one_one', [ {'template_type': 'all'}, @@ -293,7 +293,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): None, ), ( - 'folder_one_one_one – folder_one_one – folder_one – Templates – service one – U.S. Notify', + 'folder_one_one_one – folder_one_one – folder_one – Templates – service one – Notify.gov', 'Templates folder_one folder_one_one folder_one_one_one', [ {'template_type': 'email'}, @@ -311,7 +311,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): 'There are no email templates in this folder', ), ( - 'folder_two – Templates – service one – U.S. Notify', + 'folder_two – Templates – service one – Notify.gov', 'Templates folder_two', [{'template_type': 'all'}], {'template_folder_id': FOLDER_TWO_ID}, @@ -322,7 +322,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): 'This folder is empty', ), ( - 'folder_two – Templates – service one – U.S. Notify', + 'folder_two – Templates – service one – Notify.gov', 'Templates folder_two', [{'template_type': 'sms'}], {'template_folder_id': FOLDER_TWO_ID, 'template_type': 'sms'}, @@ -333,7 +333,7 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): 'This folder is empty', ), ( - 'folder_two – Templates – service one – U.S. Notify', + 'folder_two – Templates – service one – Notify.gov', 'Templates folder_two', [{'template_type': 'all'}], {'template_folder_id': FOLDER_TWO_ID, 'template_type': 'all'}, @@ -564,7 +564,7 @@ def test_get_manage_folder_page( _test_page_title=False, ) assert normalize_spaces(page.select_one('title').text) == ( - 'folder_two – Templates – service one – U.S. Notify' + 'folder_two – Templates – service one – Notify.gov' ) assert page.select_one('input[name=name]')['value'] == 'folder_two' delete_link = page.find('a', string="Delete this folder") @@ -599,7 +599,7 @@ def test_get_manage_folder_viewing_permissions_for_users( _test_page_title=False, ) assert normalize_spaces(page.select_one('title').text) == ( - 'folder_two – Templates – service one – U.S. Notify' + 'folder_two – Templates – service one – Notify.gov' ) form_labels = page.select('legend.govuk-fieldset__legend') assert normalize_spaces(form_labels[0].text) == "Team members who can see this folder" @@ -651,7 +651,7 @@ def test_get_manage_folder_viewing_permissions_for_users_not_visible_when_no_man _test_page_title=False, ) assert normalize_spaces(page.select_one('title').text) == ( - 'folder_two – Templates – service one – U.S. Notify' + 'folder_two – Templates – service one – Notify.gov' ) form_labels = page.select('legend[class=form-label]') assert len(form_labels) == 0 @@ -685,7 +685,7 @@ def test_get_manage_folder_viewing_permissions_for_users_not_visible_for_service _test_page_title=False, ) assert normalize_spaces(page.select_one('title').text) == ( - 'folder_two – Templates – service one – U.S. Notify' + 'folder_two – Templates – service one – Notify.gov' ) form_labels = page.select('legend[class=form-label]') assert len(form_labels) == 0 diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py index 61ff06f20..5899ed2f3 100644 --- a/tests/app/main/views/test_templates.py +++ b/tests/app/main/views/test_templates.py @@ -472,7 +472,7 @@ def test_caseworker_sees_template_page_if_template_is_deleted( content = str(page) assert url_for("main.send_one_off", service_id=SERVICE_ONE_ID, template_id=fake_uuid) not in content - assert page.select('p.hint')[0].text.strip() == 'This template was deleted today at 15:00.' + assert page.select('p.hint')[0].text.strip() == 'This template was deleted today at 15:00 UTC.' mock_get_deleted_template.assert_called_with(SERVICE_ONE_ID, template_id, None) @@ -554,7 +554,7 @@ def test_should_be_able_to_view_a_template_with_links( 'Review your message' ) assert normalize_spaces(page.select_one('title').text) == ( - 'Two week reminder – Templates – service one – U.S. Notify' + 'Two week reminder – Templates – service one – Notify.gov' ) assert [ @@ -1571,7 +1571,7 @@ def test_should_show_page_for_a_deleted_template( content = str(page) assert url_for("main.edit_service_template", service_id=SERVICE_ONE_ID, template_id=fake_uuid) not in content assert url_for("main.send_one_off", service_id=SERVICE_ONE_ID, template_id=fake_uuid) not in content - assert page.select('p.hint')[0].text.strip() == 'This template was deleted today at 15:00.' + assert page.select('p.hint')[0].text.strip() == 'This template was deleted today at 15:00 UTC.' assert 'Delete this template' not in page.select_one('main').text mock_get_deleted_template.assert_called_with(SERVICE_ONE_ID, template_id, None) diff --git a/tests/app/main/views/uploads/test_upload_hub.py b/tests/app/main/views/uploads/test_upload_hub.py index 780c0d0c6..4cf2acb6d 100644 --- a/tests/app/main/views/uploads/test_upload_hub.py +++ b/tests/app/main/views/uploads/test_upload_hub.py @@ -48,7 +48,7 @@ def test_get_upload_hub_page( assert normalize_spaces(uploads[0].text.strip()) == ( 'some.csv ' - 'Sent 1 January 2016 at 11:09 ' + 'Sent 1 January 2016 at 11:09 UTC ' '0 pending 8 delivered 2 failed' ) assert uploads[0].select_one('a.file-list-filename-large')['href'] == ( @@ -79,12 +79,12 @@ def test_uploads_page_shows_scheduled_jobs( ), ( 'even_later.csv ' - 'Sending 1 January 2016 at 23:09 ' + 'Sending 1 January 2016 at 23:09 UTC ' '1 text message waiting to send' ), ( 'send_me_later.csv ' - 'Sending 1 January 2016 at 11:09 ' + 'Sending 1 January 2016 at 11:09 UTC ' '1 text message waiting to send' ), ] diff --git a/tests/conftest.py b/tests/conftest.py index 79aa06b8c..69ab8864e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3384,3 +3384,15 @@ def webauthn_credential_2(): 'registration_response': 'stuff', 'created_at': '2021-05-14T16:57:14.154185Z', } + + +@pytest.fixture(scope='session') +def end_to_end_auth_context(browser): + # Create a context with HTTP Authentication credentials for Playwright E2E + # tests. + context = browser.new_context(http_credentials={ + 'username': os.environ.get('NOTIFY_STAGING_HTTP_AUTH_USER'), + 'password': os.environ.get('NOTIFY_STAGING_HTTP_AUTH_PASSWORD'), + }) + + yield context diff --git a/tests/end_to_end/test_landing_and_sign_in_pages.py b/tests/end_to_end/test_landing_and_sign_in_pages.py new file mode 100644 index 000000000..82e7d02eb --- /dev/null +++ b/tests/end_to_end/test_landing_and_sign_in_pages.py @@ -0,0 +1,109 @@ +import os +import re + +from playwright.sync_api import expect + + +def test_landing_page(end_to_end_auth_context): + # Open a new page and go to the staging site. + page = end_to_end_auth_context.new_page() + page.goto(os.environ.get('NOTIFY_STAGING_URI')) + + # Check the page title exists and matches what we expect. + expect(page).to_have_title(re.compile('U.S. Notify')) + + # Retrieve some prominent elements on the page for testing. + main_header = page.get_by_role( + 'heading', + name='Send text messages to your participants' + ) + sign_in_button = page.get_by_role('link', name='Sign in') + benefits_studio_email = page.get_by_role( + 'link', + name='tts-benefits-studio@gsa.gov' + ) + + # Check to make sure the elements are visible. + expect(main_header).to_be_visible() + expect(sign_in_button).to_be_visible() + expect(benefits_studio_email).to_be_visible() + + # Check to make sure the sign-in button and email links are correct. + expect(sign_in_button).to_have_attribute('href', '/sign-in') + expect(benefits_studio_email).to_have_attribute( + 'href', + 'mailto:tts-benefits-studio@gsa.gov' + ) + + # Retrieve all other main content headers and check that they're + # visible. + content_headers = [ + 'Control your content', + 'See how your messages perform', + 'No technical integration needed', + 'About the product', + ] + + for content_header in content_headers: + expect( + page.get_by_role('heading', name=re.compile(content_header)) + ).to_be_visible() + + +def test_sign_in_page(end_to_end_auth_context): + # Open a new page and go to the staging site. + page = end_to_end_auth_context.new_page() + page.goto(os.environ.get('NOTIFY_STAGING_URI')) + + sign_in_button = page.get_by_role('link', name='Sign in') + + # Test trying to sign in. + sign_in_button.click() + + # Check the page title exists and matches what we expect. + # NOTE: The dash is a special character! It had to be copied from + # the template itself. + # TODO: Improve this check, or change it so no special character is + # needed. Better yet, fix the template(s) character too. + expect(page).to_have_title(re.compile('Sign in – U.S. Notify')) + + # Check for the sign in heading. + sign_in_heading = page.get_by_role('heading', name='Sign in') + expect(sign_in_heading).to_be_visible() + + # Check for the sign in form elements. + # NOTE: Playwright cannot find input elements by role and recommends using + # get_by_label() instead; however, hidden form elements do not have + # labels associated with them, hence the XPath! + # See https://playwright.dev/python/docs/api/class-page#page-get-by-label + # and https://playwright.dev/python/docs/locators#locate-by-css-or-xpath + # for more information. + email_address_input = page.get_by_label('Email address') + password_input = page.get_by_label('Password') + csrf_token = page.locator('xpath=//input[@name="csrf_token"]') + continue_button = page.get_by_role('button', name=re.compile('Continue')) + forgot_password_link = page.get_by_role( + 'link', + name='Forgot your password?' + ) + + # Make sure form elements are visible and not visible as expected. + expect(email_address_input).to_be_visible() + expect(password_input).to_be_visible() + expect(continue_button).to_be_visible() + expect(forgot_password_link).to_be_visible() + + expect(csrf_token).to_be_hidden() + + # Make sure form elements are configured correctly with the right + # attributes. + expect(email_address_input).to_have_attribute('type', 'email') + expect(password_input).to_have_attribute('type', 'password') + expect(csrf_token).to_have_attribute('type', 'hidden') + expect(continue_button).to_have_attribute('type', 'submit') + expect(forgot_password_link).to_have_attribute( + 'href', + '/forgot-password' + ) + + # TODO: Figure out how to actually sign in...