merge from main and resolve conflicts
@@ -12,23 +12,21 @@
|
|||||||
|
|
||||||
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="/static/images/favicon.ico?de7abc5226925203ac10b0a4a94af949"
|
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="/static/images/favicon.ico?de7abc5226925203ac10b0a4a94af949"
|
||||||
type="image/x-icon" />
|
type="image/x-icon" />
|
||||||
<link rel="mask-icon" href="/static/images/govuk-mask-icon.svg?2afd125b1db96109388d4a0727312f3e" color="#0b0c0c">
|
<link rel="mask-icon" href="/static/images/usa-mask-icon.svg?2afd125b1db96109388d4a0727312f3e" color="#F0F0F0">
|
||||||
<link rel="apple-touch-icon" sizes="180x180"
|
<link rel="apple-touch-icon" sizes="180x180"
|
||||||
href="/static/images/govuk-apple-touch-icon-180x180.png?a0f7e1b728a42016b247dc54ee40d055">
|
href="/static/images/apple-touch-icon.png?a0f7e1b728a42016b247dc54ee40d055">
|
||||||
<link rel="apple-touch-icon" sizes="167x167"
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
|
||||||
href="/static/images/govuk-apple-touch-icon-167x167.png?f636cb7d471fc6239d2241d75cbdabcb">
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152"
|
<link rel="manifest" href="/static/images/site.webmanifest">
|
||||||
href="/static/images/govuk-apple-touch-icon-152x152.png?40846d46aa37232e2b35065769ce567c">
|
|
||||||
<link rel="apple-touch-icon" href="/static/images/govuk-apple-touch-icon.png?3c45daa1f1e716458e4da954b973002e">
|
|
||||||
|
|
||||||
<link rel="stylesheet" media="screen" href="/static/stylesheets/main.css?d077f86473501ab244de0b30600536ee" />
|
<link rel="stylesheet" media="screen" href="/static/stylesheets/main.css?d077f86473501ab244de0b30600536ee" />
|
||||||
<link rel="stylesheet" media="print" href="/static/stylesheets/print.css?28010888ca5719dc83d7c2c80f6ed2b2" />
|
<link rel="stylesheet" media="print" href="/static/stylesheets/print.css?28010888ca5719dc83d7c2c80f6ed2b2" />
|
||||||
|
|
||||||
<meta property="og:image" content="/static/images/govuk-opengraph-image.png">
|
<meta property="og:image" content="/static/images/usa-opengraph-image.png">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="usa-template__body">
|
<body class="usa-template__body">
|
||||||
<a href="#main-content" class="govuk-skip-link">Skip to main content</a>
|
<a href="#main-content" class="usa-skip-link">Skip to main content</a>
|
||||||
<header class="usa-header " role="banner" data-module="header">
|
<header class="usa-header " role="banner" data-module="header">
|
||||||
<div class="usa-header__container usa-width-container">
|
<div class="usa-header__container usa-width-container">
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 283 B |
|
After Width: | Height: | Size: 384 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1 @@
|
|||||||
|
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="680" height="680" viewBox="0 0 680 680" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M672 211H332V161L672 161V211ZM672 294H332V244H672V294ZM672 377H332V327H672V377ZM672 410V460H8V410H672ZM672 493V543H8V493H672Z" fill="#D83933"/>
|
||||||
|
<path d="M8 161H299V377H8V161Z" fill="#3C3B6E"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 349 B |
|
After Width: | Height: | Size: 15 KiB |
@@ -1,3 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Markup,
|
Markup,
|
||||||
abort,
|
abort,
|
||||||
@@ -10,9 +12,10 @@ from flask import (
|
|||||||
)
|
)
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from app import login_manager
|
from app import login_manager, user_api_client
|
||||||
from app.main import main
|
from app.main import main
|
||||||
from app.main.forms import LoginForm
|
from app.main.forms import LoginForm
|
||||||
|
from app.main.views.verify import activate_user
|
||||||
from app.models.user import InvitedUser, User
|
from app.models.user import InvitedUser, User
|
||||||
from app.utils import hide_from_search_engines
|
from app.utils import hide_from_search_engines
|
||||||
from app.utils.login import is_safe_redirect_url
|
from app.utils.login import is_safe_redirect_url
|
||||||
@@ -22,6 +25,12 @@ from app.utils.login import is_safe_redirect_url
|
|||||||
@hide_from_search_engines
|
@hide_from_search_engines
|
||||||
def sign_in():
|
def sign_in():
|
||||||
redirect_url = request.args.get("next")
|
redirect_url = request.args.get("next")
|
||||||
|
|
||||||
|
if os.getenv("NOTIFY_E2E_TEST_EMAIL"):
|
||||||
|
user = user_api_client.get_user_by_email(os.getenv("NOTIFY_E2E_TEST_EMAIL"))
|
||||||
|
activate_user(user["id"])
|
||||||
|
return redirect(url_for("main.show_accounts_or_dashboard", next=redirect_url))
|
||||||
|
|
||||||
if current_user and current_user.is_authenticated:
|
if current_user and current_user.is_authenticated:
|
||||||
if redirect_url and is_safe_redirect_url(redirect_url):
|
if redirect_url and is_safe_redirect_url(redirect_url):
|
||||||
return redirect(redirect_url)
|
return redirect(redirect_url)
|
||||||
@@ -58,6 +67,7 @@ def sign_in():
|
|||||||
|
|
||||||
if user.sms_auth:
|
if user.sms_auth:
|
||||||
return redirect(url_for(".two_factor_sms", next=redirect_url))
|
return redirect(url_for(".two_factor_sms", next=redirect_url))
|
||||||
|
|
||||||
if user.email_auth:
|
if user.email_auth:
|
||||||
return redirect(
|
return redirect(
|
||||||
url_for(".two_factor_email_sent", next=redirect_url)
|
url_for(".two_factor_email_sent", next=redirect_url)
|
||||||
|
|||||||
@@ -3,23 +3,15 @@
|
|||||||
|
|
||||||
{% block headIcons %}
|
{% block headIcons %}
|
||||||
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{ asset_url('images/favicon.ico') }}" type="image/x-icon" />
|
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{ asset_url('images/favicon.ico') }}" type="image/x-icon" />
|
||||||
<link rel="mask-icon" href="{{ asset_url('images/govuk-mask-icon.svg') }}" color="{{ themeColor | default('#0b0c0c') }}"> {# Hardcoded value of $govuk-black #}
|
<link rel="mask-icon" href="{{ asset_url('images/usa-mask-icon.svg') }}" color="{{ themeColor | default('#F0F0F0') }}">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset_url('images/govuk-apple-touch-icon-180x180.png') }}">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset_url('images/apple-touch-icon.png') }}">
|
||||||
<link rel="apple-touch-icon" sizes="167x167" href="{{ asset_url('images/govuk-apple-touch-icon-167x167.png') }}">
|
<link rel="apple-touch-icon" href="{{ asset_url('images/apple-touch-icon.png') }}">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="{{ asset_url('images/govuk-apple-touch-icon-152x152.png') }}">
|
|
||||||
<link rel="apple-touch-icon" href="{{ asset_url('images/govuk-apple-touch-icon.png') }}">
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
{%- for font in font_paths %}
|
|
||||||
<link rel="preload" href="{{ asset_url(font, with_querystring_hash=False) }}" as="font" type="font/woff2" crossorigin>
|
|
||||||
{%- endfor %}
|
|
||||||
<link rel="stylesheet" media="screen" href="{{ asset_url('css/styles.css') }}" />
|
<link rel="stylesheet" media="screen" href="{{ asset_url('css/styles.css') }}" />
|
||||||
{% block extra_stylesheets %}
|
{% block extra_stylesheets %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<style nonce="{{ csp_nonce() }}">
|
|
||||||
.govuk-header__container { border-color: {{header_colour}} }
|
|
||||||
</style>
|
|
||||||
{% if g.hide_from_search_engines %}
|
{% if g.hide_from_search_engines %}
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -28,6 +20,8 @@
|
|||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block meta %}
|
{% block meta %}
|
||||||
|
<meta property="og:site_name" content="Notify.gov">
|
||||||
|
<meta property="og:image" content="{{ asset_url('images/usa-opengraph-image.png') }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<!-- <script type="text/javascript" src="{{ asset_url('js/gtm_head.js') }}"></script> -->
|
<!-- <script type="text/javascript" src="{{ asset_url('js/gtm_head.js') }}"></script> -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -20,17 +20,17 @@
|
|||||||
|
|
||||||
{% block headIcons %}
|
{% block headIcons %}
|
||||||
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{ assetPath | default('/assets') }}/images/favicon.ico" type="image/x-icon" />
|
<link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{ assetPath | default('/assets') }}/images/favicon.ico" type="image/x-icon" />
|
||||||
<link rel="mask-icon" href="{{ assetPath | default('/assets') }}/images/govuk-mask-icon.svg" color="{{ themeColor | default('#0b0c0c') }}"> {# Hardcoded value of $govuk-black #}
|
<link rel="mask-icon" href="{{ assetPath | default('/assets') }}/images/usa-mask-icon.svg" color="{{ themeColor | default('#F0F0F0') }}">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ assetPath | default('/assets') }}/images/govuk-apple-touch-icon-180x180.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ assetPath | default('/assets') }}/images/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="167x167" href="{{ assetPath | default('/assets') }}/images/govuk-apple-touch-icon-167x167.png">
|
<link rel="apple-touch-icon" href="{{ assetPath | default('/assets') }}/images/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="{{ assetPath | default('/assets') }}/images/govuk-apple-touch-icon-152x152.png">
|
|
||||||
<link rel="apple-touch-icon" href="{{ assetPath | default('/assets') }}/images/govuk-apple-touch-icon.png">
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
{# The default og:image is added below head so that scrapers see any custom metatags first, and this is just a fallback #}
|
{# The default og:image is added below head so that scrapers see any custom metatags first, and this is just a fallback #}
|
||||||
{# image url needs to be absolute e.g. http://wwww.domain.com/.../govuk-opengraph-image.png #}
|
{% block meta %}
|
||||||
<!-- <meta property="og:image" content="{{ assetUrl | default('/assets') }}/images/govuk-opengraph-image.png"> -->
|
<meta property="og:site_name" content="Notify.gov">
|
||||||
|
<meta property="og:image" content="{{ asset_url('images/usa-opengraph-image.png') }}">
|
||||||
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body class="usa-template__body {{ bodyClasses }}">
|
<body class="usa-template__body {{ bodyClasses }}">
|
||||||
<script nonce="{{ csp_nonce() }}">document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
|
<script nonce="{{ csp_nonce() }}">document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ applications:
|
|||||||
instances: ((instances))
|
instances: ((instances))
|
||||||
memory: ((memory))
|
memory: ((memory))
|
||||||
command: newrelic-admin run-program gunicorn -c /home/vcap/app/gunicorn_config.py application
|
command: newrelic-admin run-program gunicorn -c /home/vcap/app/gunicorn_config.py application
|
||||||
health-check-type: http
|
health-check-type: port
|
||||||
health-check-http-endpoint: '/_status?simple=true'
|
|
||||||
health-check-invocation-timeout: 10
|
health-check-invocation-timeout: 10
|
||||||
routes:
|
routes:
|
||||||
- route: ((public_admin_route))
|
- route: ((public_admin_route))
|
||||||
|
|||||||
@@ -12,14 +12,9 @@
|
|||||||
|
|
||||||
<link rel="shortcut icon" sizes="16x16 32x32 48x48"
|
<link rel="shortcut icon" sizes="16x16 32x32 48x48"
|
||||||
href="/static_503/images/favicon.ico?de7abc5226925203ac10b0a4a94af949" type="image/x-icon" />
|
href="/static_503/images/favicon.ico?de7abc5226925203ac10b0a4a94af949" type="image/x-icon" />
|
||||||
<link rel="mask-icon" href="/static_503/images/govuk-mask-icon.svg?2afd125b1db96109388d4a0727312f3e" color="#0b0c0c">
|
<link rel="mask-icon" href="/static_503/images/usa-mask-icon.svg?2afd125b1db96109388d4a0727312f3e" color="#0b0c0c">
|
||||||
<link rel="apple-touch-icon" sizes="180x180"
|
<link rel="apple-touch-icon" sizes="180x180"
|
||||||
href="/static_503/images/govuk-apple-touch-icon-180x180.png?a0f7e1b728a42016b247dc54ee40d055">
|
href="/static_503/images/apple-touch-icon.png?a0f7e1b728a42016b247dc54ee40d055">
|
||||||
<link rel="apple-touch-icon" sizes="167x167"
|
|
||||||
href="/static_503/images/govuk-apple-touch-icon-167x167.png?f636cb7d471fc6239d2241d75cbdabcb">
|
|
||||||
<link rel="apple-touch-icon" sizes="152x152"
|
|
||||||
href="/static_503/images/govuk-apple-touch-icon-152x152.png?40846d46aa37232e2b35065769ce567c">
|
|
||||||
<link rel="apple-touch-icon" href="/static_503/images/govuk-apple-touch-icon.png?3c45daa1f1e716458e4da954b973002e">
|
|
||||||
|
|
||||||
<link rel="stylesheet" media="screen" href="/static_503/stylesheets/main.css?d077f86473501ab244de0b30600536ee" />
|
<link rel="stylesheet" media="screen" href="/static_503/stylesheets/main.css?d077f86473501ab244de0b30600536ee" />
|
||||||
<link rel="stylesheet" media="print" href="/static_503/stylesheets/print.css?28010888ca5719dc83d7c2c80f6ed2b2" />
|
<link rel="stylesheet" media="print" href="/static_503/stylesheets/print.css?28010888ca5719dc83d7c2c80f6ed2b2" />
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
"test-watch": "jest --watch --config tests/javascripts/jest.config.js tests/javascripts",
|
"test-watch": "jest --watch --config tests/javascripts/jest.config.js tests/javascripts",
|
||||||
"build": "gulp",
|
"build": "gulp",
|
||||||
"watch": "gulp watch",
|
"watch": "gulp watch",
|
||||||
"audit": "better-npm-audit audit --production --level low"
|
"audit": "better-npm-audit audit --production --level low",
|
||||||
|
"pa11y-ci": "pa11y-ci"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -832,13 +832,13 @@ pyflakes = ">=3.1.0,<3.2.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flake8-bugbear"
|
name = "flake8-bugbear"
|
||||||
version = "23.7.10"
|
version = "23.9.16"
|
||||||
description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle."
|
description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8.1"
|
python-versions = ">=3.8.1"
|
||||||
files = [
|
files = [
|
||||||
{file = "flake8-bugbear-23.7.10.tar.gz", hash = "sha256:0ebdc7d8ec1ca8bd49347694562381f099f4de2f8ec6bda7a7dca65555d9e0d4"},
|
{file = "flake8-bugbear-23.9.16.tar.gz", hash = "sha256:90cf04b19ca02a682feb5aac67cae8de742af70538590509941ab10ae8351f71"},
|
||||||
{file = "flake8_bugbear-23.7.10-py3-none-any.whl", hash = "sha256:d99d005114020fbef47ed5e4aebafd22f167f9a0fbd0d8bf3c9e90612cb25c34"},
|
{file = "flake8_bugbear-23.9.16-py3-none-any.whl", hash = "sha256:b182cf96ea8f7a8595b2f87321d7d9b28728f4d9c3318012d896543d19742cb5"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -2427,36 +2427,38 @@ diagrams = ["jinja2", "railroad-diagrams"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyproj"
|
name = "pyproj"
|
||||||
version = "3.6.0"
|
version = "3.6.1"
|
||||||
description = "Python interface to PROJ (cartographic projections and coordinate transformations library)"
|
description = "Python interface to PROJ (cartographic projections and coordinate transformations library)"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e600f6a2771d3b41aeb2cc1efd96771ae9a01451013da1dd48ff272e7c6e34ef"},
|
{file = "pyproj-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4"},
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d7f6cd045df29aae960391dfe06a575c110af598f1dea5add8be6ca42332b0f5"},
|
{file = "pyproj-3.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4bc0472302919e59114aa140fd7213c2370d848a7249d09704f10f5b062031fe"},
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:557e6592855111c84eda176ddf6b130f55d5e2b9cb1c017b8c91b69f37f474f5"},
|
{file = "pyproj-3.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5279586013b8d6582e22b6f9e30c49796966770389a9d5b85e25a4223286cd3f"},
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de6288b6ceabdeeac01abf627c74414822d322d8f55dc8efe4d29dedd27c5719"},
|
{file = "pyproj-3.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fafd1f3eb421694857f254a9bdbacd1eb22fc6c24ca74b136679f376f97d35"},
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e427ccdbb1763872416549bdfa9fa1f5f169054653c4daf674e71480cc39cf11"},
|
{file = "pyproj-3.6.1-cp310-cp310-win32.whl", hash = "sha256:c41e80ddee130450dcb8829af7118f1ab69eaf8169c4bf0ee8d52b72f098dc2f"},
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-win32.whl", hash = "sha256:1283d3c1960edbb74828f5f3405b27578a9a27f7766ab6a3956f4bd851f08239"},
|
{file = "pyproj-3.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:db3aedd458e7f7f21d8176f0a1d924f1ae06d725228302b872885a1c34f3119e"},
|
||||||
{file = "pyproj-3.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:9de1aab71234bfd3fd648a1152519b5ee152c43113d7d8ea52590a0140129501"},
|
{file = "pyproj-3.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ebfbdbd0936e178091309f6cd4fcb4decd9eab12aa513cdd9add89efa3ec2882"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:00fab048596c17572fa8980014ef117dbb2a445e6f7ba3b9ddfcc683efc598e7"},
|
{file = "pyproj-3.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:447db19c7efad70ff161e5e46a54ab9cc2399acebb656b6ccf63e4bc4a04b97a"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba5e7c8ddd6ed5a3f9fcf95ea80ba44c931913723de2ece841c94bb38b200c4a"},
|
{file = "pyproj-3.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e13c40183884ec7f94eb8e0f622f08f1d5716150b8d7a134de48c6110fee85"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08dfc5c9533c78a97afae9d53b99b810a4a8f97c3be9eb2b8f323b726c736403"},
|
{file = "pyproj-3.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65ad699e0c830e2b8565afe42bd58cc972b47d829b2e0e48ad9638386d994915"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18a8bdb87aeb41b60a2e91d32f623227de3569fb83b4c64b174c3a7c5b0ed3ae"},
|
{file = "pyproj-3.6.1-cp311-cp311-win32.whl", hash = "sha256:8b8acc31fb8702c54625f4d5a2a6543557bec3c28a0ef638778b7ab1d1772132"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe392dfc0eba2248dc08c976a72f52ff9da2bddfddfd9ff5dcf18e8e88200c7"},
|
{file = "pyproj-3.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:38a3361941eb72b82bd9a18f60c78b0df8408416f9340521df442cebfc4306e2"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-win32.whl", hash = "sha256:78276c6b0c831255c97c56dff7313a3571f327a284d8ac63d6a56437a72ed0e0"},
|
{file = "pyproj-3.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1e9fbaf920f0f9b4ee62aab832be3ae3968f33f24e2e3f7fbb8c6728ef1d9746"},
|
||||||
{file = "pyproj-3.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:8fbac2eb9a0e425d7d6b7c6f4ebacd675cf3bdef0c59887057b8b4b0374e7c12"},
|
{file = "pyproj-3.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d227a865356f225591b6732430b1d1781e946893789a609bb34f59d09b8b0f8"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:95120d65cbc5983dfd877076f28dbc18b9b329cbee38ca6e217bb7a5a043c099"},
|
{file = "pyproj-3.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83039e5ae04e5afc974f7d25ee0870a80a6bd6b7957c3aca5613ccbe0d3e72bf"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:830e6de7cfe43853967afee5ef908dfd5aa72d1ec12af9b9e3fecc179886e346"},
|
{file = "pyproj-3.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb059ba3bced6f6725961ba758649261d85ed6ce670d3e3b0a26e81cf1aa8d"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e342b3010b2b20134671564ff9a8c476e5e512bf589477480aded1a5813af7c8"},
|
{file = "pyproj-3.6.1-cp312-cp312-win32.whl", hash = "sha256:2d6ff73cc6dbbce3766b6c0bce70ce070193105d8de17aa2470009463682a8eb"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23787460fab85ba2f857ee60ffb2e8e21fd9bd5db9833c51c1c05b2a6d9f0be5"},
|
{file = "pyproj-3.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:7a27151ddad8e1439ba70c9b4b2b617b290c39395fa9ddb7411ebb0eb86d6fb0"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595376e4d3bb72b7dceeccbce0f4c43053d47561f17a1ad0224407e9980ee849"},
|
{file = "pyproj-3.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ba1f9b03d04d8cab24d6375609070580a26ce76eaed54631f03bab00a9c737b"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-win32.whl", hash = "sha256:4d8a9773503085eada59b6892c96ddf686ab8cf64cfdc18ad744d13ee76dfa6f"},
|
{file = "pyproj-3.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18faa54a3ca475bfe6255156f2f2874e9a1c8917b0004eee9f664b86ccc513d3"},
|
||||||
{file = "pyproj-3.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:137a07404f937f264b11b7130cd4cfa00002dbe4333b222e8056db84849c2ea4"},
|
{file = "pyproj-3.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd43bd9a9b9239805f406fd82ba6b106bf4838d9ef37c167d3ed70383943ade1"},
|
||||||
{file = "pyproj-3.6.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2799499a4045e4fb73e44c31bdacab0593a253a7a4b6baae6fdd27d604cf9bc2"},
|
{file = "pyproj-3.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50100b2726a3ca946906cbaa789dd0749f213abf0cbb877e6de72ca7aa50e1ae"},
|
||||||
{file = "pyproj-3.6.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f04f6297c615c3b17f835df2556ac8fb9b4f51f281e960437eaf0cd80e7ae26a"},
|
{file = "pyproj-3.6.1-cp39-cp39-win32.whl", hash = "sha256:9274880263256f6292ff644ca92c46d96aa7e57a75c6df3f11d636ce845a1877"},
|
||||||
{file = "pyproj-3.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a4d2d438b007cb1f8d5f6f308d53d7ff9a2508cff8f9da6e2a93b76ffd98aaf"},
|
{file = "pyproj-3.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:36b64c2cb6ea1cc091f329c5bd34f9c01bb5da8c8e4492c709bda6a09f96808f"},
|
||||||
{file = "pyproj-3.6.0.tar.gz", hash = "sha256:a5b111865b3f0f8b77b3983f2fbe4dd6248fc09d3730295949977c8dcd988062"},
|
{file = "pyproj-3.6.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd93c1a0c6c4aedc77c0fe275a9f2aba4d59b8acf88cebfc19fe3c430cfabf4f"},
|
||||||
|
{file = "pyproj-3.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6420ea8e7d2a88cb148b124429fba8cd2e0fae700a2d96eab7083c0928a85110"},
|
||||||
|
{file = "pyproj-3.6.1.tar.gz", hash = "sha256:44aa7c704c2b7d8fb3d483bbf75af6cb2350d30a63b144279a09b75fead501bf"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -3491,12 +3493,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "acc2115b5eaa279182864792a37cca84eb5ac24b4901a896c7ffa12b71e5f378"
|
content-hash = "3d8f02aa66cdf17e8295d198f663dbd21eb0ea9bfd22d72f2e8563dd26de50e4"
|
||||||
|
|
||||||
|
|
||||||
cf login -a api.fr.cloud.gov --sso
|
|
||||||
|
|
||||||
cf t -s notify-staging
|
|
||||||
|
|
||||||
cf logs notify-staging-api (get list of apps with cf apps)
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ pyexcel-ods3 = "==0.6.1"
|
|||||||
pyexcel-xls = "==0.7.0"
|
pyexcel-xls = "==0.7.0"
|
||||||
pyexcel-xlsx = "==0.6.0"
|
pyexcel-xlsx = "==0.6.0"
|
||||||
openpyxl = "==3.0.10"
|
openpyxl = "==3.0.10"
|
||||||
pyproj = "==3.6.0"
|
pyproj = "==3.6.1"
|
||||||
python-dotenv = "==1.0.0"
|
python-dotenv = "==1.0.0"
|
||||||
pytz = "==2023.3.post1"
|
pytz = "==2023.3.post1"
|
||||||
rtreelib = "==0.2.0"
|
rtreelib = "==0.2.0"
|
||||||
@@ -53,9 +53,9 @@ pytest-xdist = "==3.3.1"
|
|||||||
beautifulsoup4 = "==4.12.2"
|
beautifulsoup4 = "==4.12.2"
|
||||||
freezegun = "==1.2.2"
|
freezegun = "==1.2.2"
|
||||||
flake8 = "==6.1.0"
|
flake8 = "==6.1.0"
|
||||||
flake8-bugbear = "==23.7.10"
|
flake8-bugbear = "==23.9.16"
|
||||||
flake8-print = "==5.0.0"
|
flake8-print = "==5.0.0"
|
||||||
moto = "~=4.1"
|
moto = "~=4.2"
|
||||||
requests-mock = "==1.11.0"
|
requests-mock = "==1.11.0"
|
||||||
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
|
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
|
||||||
pip-audit = "*"
|
pip-audit = "*"
|
||||||
|
|||||||
@@ -294,26 +294,6 @@ def test_email_branding_preview(
|
|||||||
assert mock_get_email_branding.called is email_branding_retrieved
|
assert mock_get_email_branding.called is email_branding_retrieved
|
||||||
|
|
||||||
|
|
||||||
def test_font_preload(
|
|
||||||
client_request,
|
|
||||||
mock_get_service_and_organization_counts,
|
|
||||||
):
|
|
||||||
client_request.logout()
|
|
||||||
page = client_request.get("main.index", _test_page_title=False)
|
|
||||||
|
|
||||||
preload_tags = page.select(
|
|
||||||
'link[rel=preload][as=font][type="font/woff2"][crossorigin]'
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
len(preload_tags) == 4
|
|
||||||
), "Run `npm run build` to copy fonts into app/static/fonts/"
|
|
||||||
|
|
||||||
for element in preload_tags:
|
|
||||||
assert element["href"].startswith("https://static.example.com/fonts/")
|
|
||||||
assert element["href"].endswith(".woff2")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("current_date, expected_rate", (("2022-05-01", "1.72"),))
|
@pytest.mark.parametrize("current_date, expected_rate", (("2022-05-01", "1.72"),))
|
||||||
@pytest.mark.skip(reason="Currently hidden for TTS")
|
@pytest.mark.skip(reason="Currently hidden for TTS")
|
||||||
def test_sms_price(
|
def test_sms_price(
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from uuid import UUID, uuid4
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from dotenv import load_dotenv
|
||||||
from flask import Flask, url_for
|
from flask import Flask, url_for
|
||||||
from notifications_python_client.errors import HTTPError
|
from notifications_python_client.errors import HTTPError
|
||||||
from notifications_utils.url_safe_token import generate_token
|
from notifications_utils.url_safe_token import generate_token
|
||||||
@@ -33,6 +34,8 @@ from . import (
|
|||||||
user_json,
|
user_json,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
class ElementNotFound(Exception):
|
class ElementNotFound(Exception):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -2,50 +2,45 @@ import datetime
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import pytest
|
|
||||||
from playwright.sync_api import expect
|
from playwright.sync_api import expect
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="Not authenticating test users.")
|
def _bypass_sign_in(end_to_end_context):
|
||||||
def test_accounts_page(end_to_end_authenticated_context):
|
|
||||||
# Open a new page and go to the staging site.
|
# Open a new page and go to the staging site.
|
||||||
page = end_to_end_authenticated_context.new_page()
|
page = end_to_end_context.new_page()
|
||||||
|
|
||||||
accounts_uri = "{}accounts".format(os.getenv("NOTIFY_E2E_TEST_URI"))
|
page.goto(os.getenv("NOTIFY_E2E_TEST_URI"))
|
||||||
|
|
||||||
page.goto(accounts_uri)
|
sign_in_button = page.get_by_role("link", name="Sign in")
|
||||||
|
|
||||||
# Check to make sure that we've arrived at the next page.
|
# Test trying to sign in. Because we are loading the email and password
|
||||||
|
sign_in_button.click()
|
||||||
|
|
||||||
|
# Wait for the next page to fully load.
|
||||||
|
page.wait_for_load_state("domcontentloaded")
|
||||||
|
return page
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_new_service_workflow(end_to_end_context):
|
||||||
|
# page = end_to_end_context.new_page()
|
||||||
|
page = _bypass_sign_in(end_to_end_context)
|
||||||
|
page.goto(os.getenv("NOTIFY_E2E_TEST_URI"))
|
||||||
|
|
||||||
|
# sign_in_button = page.get_by_role("link", name="Sign in")
|
||||||
|
#
|
||||||
|
# Test trying to sign in. Because we are loading the email and password
|
||||||
|
# sign_in_button.click()
|
||||||
|
#
|
||||||
|
# Wait for the next page to fully load.
|
||||||
page.wait_for_load_state("domcontentloaded")
|
page.wait_for_load_state("domcontentloaded")
|
||||||
|
|
||||||
# Check to make sure that we've arrived at the next page.
|
|
||||||
# Check the page title exists and matches what we expect.
|
|
||||||
expect(page).to_have_title(re.compile("Choose service"))
|
|
||||||
|
|
||||||
# Check for the sign in heading.
|
|
||||||
sign_in_heading = page.get_by_role("heading", name="Choose service")
|
|
||||||
expect(sign_in_heading).to_be_visible()
|
|
||||||
|
|
||||||
# Retrieve some prominent elements on the page for testing.
|
|
||||||
add_service_button = page.get_by_role(
|
|
||||||
"button", name=re.compile("Add a new service")
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(add_service_button).to_be_visible()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="Not authenticating test users.")
|
|
||||||
def test_add_new_service_workflow(end_to_end_authenticated_context):
|
|
||||||
# Prepare for adding a new service later in the test.
|
# Prepare for adding a new service later in the test.
|
||||||
current_date_time = datetime.datetime.now()
|
current_date_time = datetime.datetime.now()
|
||||||
new_service_name = "E2E Federal Test Service {now} - {browser_type}".format(
|
new_service_name = "E2E Federal Test Service {now} - {browser_type}".format(
|
||||||
now=current_date_time.strftime("%m/%d/%Y %H:%M:%S"),
|
now=current_date_time.strftime("%m/%d/%Y %H:%M:%S"),
|
||||||
browser_type=end_to_end_authenticated_context.browser.browser_type.name,
|
browser_type=end_to_end_context.browser.browser_type.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Open a new page and go to the staging site.
|
|
||||||
page = end_to_end_authenticated_context.new_page()
|
|
||||||
|
|
||||||
accounts_uri = "{}accounts".format(os.getenv("NOTIFY_E2E_TEST_URI"))
|
accounts_uri = "{}accounts".format(os.getenv("NOTIFY_E2E_TEST_URI"))
|
||||||
|
|
||||||
page.goto(accounts_uri)
|
page.goto(accounts_uri)
|
||||||
@@ -100,7 +95,11 @@ def test_add_new_service_workflow(end_to_end_authenticated_context):
|
|||||||
|
|
||||||
# Fill in the form.
|
# Fill in the form.
|
||||||
service_name_input.fill(new_service_name)
|
service_name_input.fill(new_service_name)
|
||||||
federal_radio_button.click()
|
expect(federal_radio_button).to_be_enabled()
|
||||||
|
# Trying to click directly on the radio button resulted in a "not in viewport error" and this is the
|
||||||
|
# suggested workaround. Googling, the reason seems to be that there might be some (invisible?) css positioned
|
||||||
|
# above the radio button itself.
|
||||||
|
page.click("text='Federal government'")
|
||||||
|
|
||||||
# Click on add service.
|
# Click on add service.
|
||||||
add_service_button.click()
|
add_service_button.click()
|
||||||
@@ -112,3 +111,22 @@ def test_add_new_service_workflow(end_to_end_authenticated_context):
|
|||||||
service_heading = page.get_by_text(new_service_name)
|
service_heading = page.get_by_text(new_service_name)
|
||||||
expect(service_heading).to_be_visible()
|
expect(service_heading).to_be_visible()
|
||||||
expect(page).to_have_title(re.compile(new_service_name))
|
expect(page).to_have_title(re.compile(new_service_name))
|
||||||
|
|
||||||
|
page.click("text='Settings'")
|
||||||
|
|
||||||
|
# Check to make sure that we've arrived at the next page.
|
||||||
|
page.wait_for_load_state("domcontentloaded")
|
||||||
|
|
||||||
|
page.click("text='Delete this service'")
|
||||||
|
|
||||||
|
# Check to make sure that we've arrived at the next page.
|
||||||
|
page.wait_for_load_state("domcontentloaded")
|
||||||
|
|
||||||
|
page.click("text='Yes, delete'")
|
||||||
|
|
||||||
|
# Check to make sure that we've arrived at the next page.
|
||||||
|
page.wait_for_load_state("domcontentloaded")
|
||||||
|
|
||||||
|
# Check to make sure that we've arrived at the next page.
|
||||||
|
# Check the page title exists and matches what we expect.
|
||||||
|
expect(page).to_have_title(re.compile("Choose service"))
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import pytest
|
|
||||||
from playwright.sync_api import expect
|
from playwright.sync_api import expect
|
||||||
|
|
||||||
|
|
||||||
def test_landing_page(end_to_end_context):
|
def test_landing_page(end_to_end_context):
|
||||||
# Open a new page and go to the staging site.
|
# Open a new page and go to the staging site.
|
||||||
page = end_to_end_context.new_page()
|
page = end_to_end_context.browser.new_page()
|
||||||
page.goto(os.getenv("NOTIFY_E2E_TEST_URI"))
|
page.goto(os.getenv("NOTIFY_E2E_TEST_URI"))
|
||||||
|
|
||||||
# Check to make sure that we've arrived at the next page.
|
# Check to make sure that we've arrived at the next page.
|
||||||
@@ -49,118 +48,120 @@ def test_landing_page(end_to_end_context):
|
|||||||
).to_be_visible()
|
).to_be_visible()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="Not authenticating test users.")
|
# def test_sign_in_and_mfa_pages(end_to_end_context):
|
||||||
def test_sign_in_and_mfa_pages(end_to_end_context):
|
# # Open a new page and go to the staging site.
|
||||||
# Open a new page and go to the staging site.
|
# page = end_to_end_context.new_page()
|
||||||
page = end_to_end_context.new_page()
|
# page.goto(os.getenv("NOTIFY_E2E_TEST_URI"))
|
||||||
page.goto(os.getenv("NOTIFY_E2E_TEST_URI"))
|
# print(f"test_sign_in_and_mfa_pages initial {page}")
|
||||||
|
#
|
||||||
sign_in_button = page.get_by_role("link", name="Sign in")
|
# sign_in_button = page.get_by_role("link", name="Sign in")
|
||||||
|
#
|
||||||
# Test trying to sign in.
|
# # Test trying to sign in.
|
||||||
sign_in_button.click()
|
# sign_in_button.click()
|
||||||
|
#
|
||||||
# Check to make sure that we've arrived at the next page.
|
# # Check to make sure that we've arrived at the next page.
|
||||||
page.wait_for_load_state("domcontentloaded")
|
# page.wait_for_load_state("domcontentloaded")
|
||||||
|
#
|
||||||
# Check the page title exists and matches what we expect.
|
# # Check the page title exists and matches what we expect.
|
||||||
expect(page).to_have_title(re.compile("Sign in"))
|
# expect(page).to_have_title(re.compile("Sign in"))
|
||||||
|
#
|
||||||
# Check for the sign in heading.
|
# # Check for the sign in heading.
|
||||||
sign_in_heading = page.get_by_role("heading", name="Sign in")
|
# sign_in_heading = page.get_by_role("heading", name="Sign in")
|
||||||
expect(sign_in_heading).to_be_visible()
|
# expect(sign_in_heading).to_be_visible()
|
||||||
|
#
|
||||||
# Check for the sign in form elements.
|
# # Check for the sign in form elements.
|
||||||
# NOTE: Playwright cannot find input elements by role and recommends using
|
# # NOTE: Playwright cannot find input elements by role and recommends using
|
||||||
# get_by_label() instead; however, hidden form elements do not have
|
# # get_by_label() instead; however, hidden form elements do not have
|
||||||
# labels associated with them, hence the XPath!
|
# # labels associated with them, hence the XPath!
|
||||||
# See https://playwright.dev/python/docs/api/class-page#page-get-by-label
|
# # 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
|
# # and https://playwright.dev/python/docs/locators#locate-by-css-or-xpath
|
||||||
# for more information.
|
# # for more information.
|
||||||
email_address_input = page.get_by_label("Email address")
|
# email_address_input = page.get_by_label("Email address")
|
||||||
password_input = page.get_by_label("Password")
|
# password_input = page.get_by_label("Password")
|
||||||
csrf_token = page.locator('xpath=//input[@name="csrf_token"]')
|
# csrf_token = page.locator('xpath=//input[@name="csrf_token"]')
|
||||||
continue_button = page.get_by_role("button", name=re.compile("Continue"))
|
# continue_button = page.get_by_role("button", name=re.compile("Continue"))
|
||||||
forgot_password_link = page.get_by_role("link", name="Forgot your password?")
|
# forgot_password_link = page.get_by_role("link", name="Forgot your password?")
|
||||||
|
#
|
||||||
# Make sure form elements are visible and not visible as expected.
|
# # Make sure form elements are visible and not visible as expected.
|
||||||
expect(email_address_input).to_be_visible()
|
# expect(email_address_input).to_be_visible()
|
||||||
expect(password_input).to_be_visible()
|
# expect(password_input).to_be_visible()
|
||||||
expect(continue_button).to_be_visible()
|
# expect(continue_button).to_be_visible()
|
||||||
expect(forgot_password_link).to_be_visible()
|
# expect(forgot_password_link).to_be_visible()
|
||||||
|
#
|
||||||
expect(csrf_token).to_be_hidden()
|
# expect(csrf_token).to_be_hidden()
|
||||||
|
#
|
||||||
# Make sure form elements are configured correctly with the right
|
# # Make sure form elements are configured correctly with the right
|
||||||
# attributes.
|
# # attributes.
|
||||||
expect(email_address_input).to_have_attribute("type", "email")
|
# expect(email_address_input).to_have_attribute("type", "email")
|
||||||
expect(password_input).to_have_attribute("type", "password")
|
# expect(password_input).to_have_attribute("type", "password")
|
||||||
expect(csrf_token).to_have_attribute("type", "hidden")
|
# expect(csrf_token).to_have_attribute("type", "hidden")
|
||||||
expect(continue_button).to_have_attribute("type", "submit")
|
# expect(continue_button).to_have_attribute("type", "submit")
|
||||||
expect(forgot_password_link).to_have_attribute("href", "/forgot-password")
|
# expect(forgot_password_link).to_have_attribute("href", "/forgot-password")
|
||||||
|
#
|
||||||
# Sign in to the site.
|
# # Sign in to the site.
|
||||||
email_address_input.fill(os.getenv("NOTIFY_E2E_TEST_EMAIL"))
|
# email_address_input.fill(os.getenv("NOTIFY_E2E_TEST_EMAIL"))
|
||||||
password_input.fill(os.getenv("NOTIFY_E2E_TEST_PASSWORD"))
|
# password_input.fill(os.getenv("NOTIFY_E2E_TEST_PASSWORD"))
|
||||||
continue_button.click()
|
# print(f"email and password {os.getenv('NOTIFY_E2E_TEST_EMAIL')} {os.getenv('NOTIFY_E2E_TEST_PASSWORD')}")
|
||||||
|
# continue_button.click()
|
||||||
# Wait for the next page to fully load.
|
#
|
||||||
page.wait_for_load_state("domcontentloaded")
|
# # Wait for the next page to fully load.
|
||||||
|
# page.wait_for_load_state("domcontentloaded")
|
||||||
# Check the page title exists and matches what we expect.
|
#
|
||||||
expect(page).to_have_title(re.compile("Check your phone"))
|
# # Check the page title exists and matches what we expect.
|
||||||
|
# print(f"test_sign_in_and_mfa_pages finally is {page}")
|
||||||
# Check for the sign in heading.
|
# expect(page).to_have_title(re.compile("Check your phone"))
|
||||||
sign_in_heading = page.get_by_role("heading", name="Check your phone")
|
#
|
||||||
expect(sign_in_heading).to_be_visible()
|
# # Check for the sign in heading.
|
||||||
|
# sign_in_heading = page.get_by_role("heading", name="Check your phone")
|
||||||
# Check for the sign in form elements.
|
# expect(sign_in_heading).to_be_visible()
|
||||||
# NOTE: Playwright cannot find input elements by role and recommends using
|
#
|
||||||
# get_by_label() instead; however, hidden form elements do not have
|
# # Check for the sign in form elements.
|
||||||
# labels associated with them, hence the XPath!
|
# # NOTE: Playwright cannot find input elements by role and recommends using
|
||||||
# See https://playwright.dev/python/docs/api/class-page#page-get-by-label
|
# # get_by_label() instead; however, hidden form elements do not have
|
||||||
# and https://playwright.dev/python/docs/locators#locate-by-css-or-xpath
|
# # labels associated with them, hence the XPath!
|
||||||
# for more information.
|
# # See https://playwright.dev/python/docs/api/class-page#page-get-by-label
|
||||||
mfa_input = page.get_by_label("Text message code")
|
# # and https://playwright.dev/python/docs/locators#locate-by-css-or-xpath
|
||||||
csrf_token = page.locator('xpath=//input[@name="csrf_token"]')
|
# # for more information.
|
||||||
continue_button = page.get_by_role("button", name=re.compile("Continue"))
|
# mfa_input = page.get_by_label("Text message code")
|
||||||
not_received_message_link = page.get_by_role(
|
# csrf_token = page.locator('xpath=//input[@name="csrf_token"]')
|
||||||
"link", name="Not received a text message?"
|
# continue_button = page.get_by_role("button", name=re.compile("Continue"))
|
||||||
)
|
# not_received_message_link = page.get_by_role(
|
||||||
|
# "link", name="Not received a text message?"
|
||||||
# Make sure form elements are visible and not visible as expected.
|
# )
|
||||||
expect(mfa_input).to_be_visible()
|
#
|
||||||
expect(continue_button).to_be_visible()
|
# # Make sure form elements are visible and not visible as expected.
|
||||||
expect(not_received_message_link).to_be_visible()
|
# expect(mfa_input).to_be_visible()
|
||||||
|
# expect(continue_button).to_be_visible()
|
||||||
expect(csrf_token).to_be_hidden()
|
# expect(not_received_message_link).to_be_visible()
|
||||||
|
#
|
||||||
# Make sure form elements are configured correctly with the right
|
# expect(csrf_token).to_be_hidden()
|
||||||
# attributes.
|
#
|
||||||
expect(mfa_input).to_have_attribute("type", "tel")
|
# # Make sure form elements are configured correctly with the right
|
||||||
expect(mfa_input).to_have_attribute("pattern", "[0-9]*")
|
# # attributes.
|
||||||
expect(csrf_token).to_have_attribute("type", "hidden")
|
# expect(mfa_input).to_have_attribute("type", "tel")
|
||||||
expect(continue_button).to_have_attribute("type", "submit")
|
# expect(mfa_input).to_have_attribute("pattern", "[0-9]*")
|
||||||
expect(not_received_message_link).to_have_attribute("href", "/text-not-received")
|
# expect(csrf_token).to_have_attribute("type", "hidden")
|
||||||
|
# expect(continue_button).to_have_attribute("type", "submit")
|
||||||
# Enter MFA code and continue.
|
# expect(not_received_message_link).to_have_attribute("href", "/text-not-received")
|
||||||
# TODO: Revisit this at a later point in time.
|
#
|
||||||
# totp = pyotp.TOTP(
|
# # Enter MFA code and continue.
|
||||||
# os.getenv('MFA_TOTP_SECRET'),
|
# # TODO: Revisit this at a later point in time.
|
||||||
# digits=int(os.getenv('MFA_TOTP_LENGTH'))
|
# # totp = pyotp.TOTP(
|
||||||
# )
|
# # os.getenv('MFA_TOTP_SECRET'),
|
||||||
|
# # digits=int(os.getenv('MFA_TOTP_LENGTH'))
|
||||||
# mfa_input.fill('totp.now()')
|
# # )
|
||||||
# continue_button.click()
|
#
|
||||||
|
# # mfa_input.fill('totp.now()')
|
||||||
# # Check to make sure that we've arrived at the next page.
|
# # continue_button.click()
|
||||||
# page.wait_for_load_state('domcontentloaded')
|
#
|
||||||
|
# # # Check to make sure that we've arrived at the next page.
|
||||||
# # Check that no MFA code error happened.
|
# # page.wait_for_load_state('domcontentloaded')
|
||||||
# code_not_found_error = page.get_by_text('Code not found')
|
#
|
||||||
# expect(code_not_found_error).to_have_count(0)
|
# # # Check that no MFA code error happened.
|
||||||
|
# # code_not_found_error = page.get_by_text('Code not found')
|
||||||
# # Check the page title exists and matches what we expect.
|
# # expect(code_not_found_error).to_have_count(0)
|
||||||
# # This could be either the Dashboard of a service if there is only
|
#
|
||||||
# # one, or choosing a service if there are multiple.
|
# # # Check the page title exists and matches what we expect.
|
||||||
# expect(page).to_have_title(re.compile('Dashboard|Choose service'))
|
# # # This could be either the Dashboard of a service if there is only
|
||||||
|
# # # one, or choosing a service if there are multiple.
|
||||||
|
# # expect(page).to_have_title(re.compile('Dashboard|Choose service'))
|
||||||
|
|||||||