mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-11 10:28:41 -04:00
merge from main
This commit is contained in:
@@ -15,7 +15,7 @@ NVMSH := $(shell [ -f "$(HOME)/.nvm/nvm.sh" ] && echo "$(HOME)/.nvm/nvm.sh" || e
|
|||||||
|
|
||||||
.PHONY: bootstrap
|
.PHONY: bootstrap
|
||||||
bootstrap: generate-version-file ## Set up everything to run the app
|
bootstrap: generate-version-file ## Set up everything to run the app
|
||||||
poetry install
|
poetry install --sync
|
||||||
poetry run playwright install --with-deps
|
poetry run playwright install --with-deps
|
||||||
source $(NVMSH) --no-use && nvm install && npm ci --no-audit
|
source $(NVMSH) --no-use && nvm install && npm ci --no-audit
|
||||||
source $(NVMSH) && npm run build
|
source $(NVMSH) && npm run build
|
||||||
@@ -95,6 +95,14 @@ fix-imports: ## Fix imports using isort
|
|||||||
.PHONY: py-lock
|
.PHONY: py-lock
|
||||||
py-lock: ## Syncs dependencies and updates lock file without performing recursive internal updates
|
py-lock: ## Syncs dependencies and updates lock file without performing recursive internal updates
|
||||||
poetry lock --no-update
|
poetry lock --no-update
|
||||||
|
poetry install --sync
|
||||||
|
|
||||||
|
.PHONY: update-utils
|
||||||
|
update-utils: ## Forces Poetry to pull the latest changes from the notifications-utils repo; requires that you commit the changes to poetry.lock!
|
||||||
|
poetry update notifications-utils
|
||||||
|
@echo
|
||||||
|
@echo !!! PLEASE MAKE SURE TO COMMIT AND PUSH THE UPDATED poetry.lock FILE !!!
|
||||||
|
@echo
|
||||||
|
|
||||||
.PHONY: freeze-requirements
|
.PHONY: freeze-requirements
|
||||||
freeze-requirements: ## create static requirements.txt
|
freeze-requirements: ## create static requirements.txt
|
||||||
@@ -105,7 +113,7 @@ pip-audit:
|
|||||||
poetry requirements > requirements.txt
|
poetry requirements > requirements.txt
|
||||||
poetry requirements --dev > requirements_for_test.txt
|
poetry requirements --dev > requirements_for_test.txt
|
||||||
poetry run pip-audit -r requirements.txt
|
poetry run pip-audit -r requirements.txt
|
||||||
-poetry run pip-audit -r requirements_for_test.txt
|
poetry run pip-audit -r requirements_for_test.txt
|
||||||
|
|
||||||
.PHONY: audit
|
.PHONY: audit
|
||||||
audit: npm-audit pip-audit
|
audit: npm-audit pip-audit
|
||||||
|
|||||||
@@ -102,6 +102,23 @@ In either situation, once you are finished and have verified the dependency
|
|||||||
changes are working, please be sure to commit both the `pyproject.toml` and
|
changes are working, please be sure to commit both the `pyproject.toml` and
|
||||||
`poetry.lock` files.
|
`poetry.lock` files.
|
||||||
|
|
||||||
|
### Keeping the notification-utils dependency up-to-date
|
||||||
|
|
||||||
|
The `notifications-utils` dependency references the other repository we have at
|
||||||
|
https://github.com/GSA/notifications-utils - this dependency requires a bit of
|
||||||
|
extra legwork to ensure it stays up-to-date.
|
||||||
|
|
||||||
|
Whenever a PR is merged in the `notifications-utils` repository, we need to make
|
||||||
|
sure the changes are pulled in here and committed to this repository as well.
|
||||||
|
You can do this by going through these steps:
|
||||||
|
|
||||||
|
- Make sure your local `main` branch is up-to-date
|
||||||
|
- Create a new branch to work in
|
||||||
|
- Run `make update-utils`
|
||||||
|
- Commit the updated `poetry.lock` file and push the changes
|
||||||
|
- Make a new PR with the change
|
||||||
|
- Have the PR get reviewed and merged
|
||||||
|
|
||||||
## To test the application
|
## To test the application
|
||||||
|
|
||||||
From a terminal within the running devcontainer:
|
From a terminal within the running devcontainer:
|
||||||
|
|||||||
+15
-4
@@ -285,11 +285,22 @@ def init_app(application):
|
|||||||
@application.context_processor
|
@application.context_processor
|
||||||
def _attach_current_global_daily_messages():
|
def _attach_current_global_daily_messages():
|
||||||
remaining_global_messages = 0
|
remaining_global_messages = 0
|
||||||
|
|
||||||
if current_app:
|
if current_app:
|
||||||
global_limit = current_app.config["GLOBAL_SERVICE_MESSAGE_LIMIT"]
|
if request.view_args:
|
||||||
global_messages_count = service_api_client.get_global_notification_count()
|
service_id = request.view_args.get(
|
||||||
remaining_global_messages = global_limit - global_messages_count
|
"service_id", session.get("service_id")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
service_id = session.get("service_id")
|
||||||
|
|
||||||
|
if service_id:
|
||||||
|
global_limit = current_app.config["GLOBAL_SERVICE_MESSAGE_LIMIT"]
|
||||||
|
global_messages_count = (
|
||||||
|
service_api_client.get_global_notification_count(service_id)
|
||||||
|
)
|
||||||
|
remaining_global_messages = global_limit - global_messages_count.get(
|
||||||
|
"count"
|
||||||
|
)
|
||||||
return {"daily_global_messages_remaining": remaining_global_messages}
|
return {"daily_global_messages_remaining": remaining_global_messages}
|
||||||
|
|
||||||
@application.before_request
|
@application.before_request
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ def terms():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@main.route("/features/using-notify")
|
@main.route("/features/using_notify")
|
||||||
@user_is_logged_in
|
@user_is_logged_in
|
||||||
def using_notify():
|
def using_notify():
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -61,6 +61,82 @@ class HeaderNavigation(Navigation):
|
|||||||
"message_status",
|
"message_status",
|
||||||
"guidance_index",
|
"guidance_index",
|
||||||
},
|
},
|
||||||
|
"accounts-or-dashboard": {
|
||||||
|
"conversation",
|
||||||
|
"inbox",
|
||||||
|
"monthly",
|
||||||
|
"service_dashboard",
|
||||||
|
"template_usage",
|
||||||
|
"view_notification",
|
||||||
|
"view_notifications",
|
||||||
|
"action_blocked",
|
||||||
|
"add_service_template",
|
||||||
|
"check_messages",
|
||||||
|
"check_notification",
|
||||||
|
"choose_template",
|
||||||
|
"choose_template_to_copy",
|
||||||
|
"confirm_redact_template",
|
||||||
|
"conversation_reply",
|
||||||
|
"copy_template",
|
||||||
|
"delete_service_template",
|
||||||
|
"edit_service_template",
|
||||||
|
"manage_template_folder",
|
||||||
|
"send_messages",
|
||||||
|
"send_one_off",
|
||||||
|
"send_one_off_step",
|
||||||
|
"send_one_off_to_myself",
|
||||||
|
"set_sender",
|
||||||
|
"set_template_sender",
|
||||||
|
"view_template",
|
||||||
|
"view_template_version",
|
||||||
|
"view_template_versions",
|
||||||
|
"uploads",
|
||||||
|
"view_job",
|
||||||
|
"view_jobs",
|
||||||
|
"confirm_edit_user_email",
|
||||||
|
"confirm_edit_user_mobile_number",
|
||||||
|
"edit_user_email",
|
||||||
|
"edit_user_mobile_number",
|
||||||
|
"edit_user_permissions",
|
||||||
|
"invite_user",
|
||||||
|
"manage_users",
|
||||||
|
"remove_user_from_service",
|
||||||
|
"usage",
|
||||||
|
"email_branding_govuk",
|
||||||
|
"email_branding_govuk_and_org",
|
||||||
|
"email_branding_organization",
|
||||||
|
"email_branding_request",
|
||||||
|
"email_branding_something_else",
|
||||||
|
"estimate_usage",
|
||||||
|
"link_service_to_organization",
|
||||||
|
"request_to_go_live",
|
||||||
|
"service_add_email_reply_to",
|
||||||
|
"service_add_sms_sender",
|
||||||
|
"service_confirm_delete_email_reply_to",
|
||||||
|
"service_confirm_delete_sms_sender",
|
||||||
|
"service_edit_email_reply_to",
|
||||||
|
"service_edit_sms_sender",
|
||||||
|
"service_email_reply_to",
|
||||||
|
"service_name_change",
|
||||||
|
"service_preview_email_branding",
|
||||||
|
"service_set_auth_type",
|
||||||
|
"service_set_channel",
|
||||||
|
"send_files_by_email_contact_details",
|
||||||
|
"service_set_email_branding",
|
||||||
|
"service_set_inbound_number",
|
||||||
|
"service_set_inbound_sms",
|
||||||
|
"service_set_international_sms",
|
||||||
|
"service_set_reply_to_email",
|
||||||
|
"service_set_sms_prefix",
|
||||||
|
"service_verify_reply_to_address",
|
||||||
|
"service_verify_reply_to_address_updates",
|
||||||
|
"service_settings",
|
||||||
|
"service_sms_senders",
|
||||||
|
"set_free_sms_allowance",
|
||||||
|
"set_message_limit",
|
||||||
|
"set_rate_limit",
|
||||||
|
"submit_request_to_go_live",
|
||||||
|
},
|
||||||
"pricing": {
|
"pricing": {
|
||||||
"how_to_pay",
|
"how_to_pay",
|
||||||
"billing_details",
|
"billing_details",
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ from datetime import datetime
|
|||||||
from app.extensions import redis_client
|
from app.extensions import redis_client
|
||||||
from app.notify_client import NotifyAdminAPIClient, _attach_current_user, cache
|
from app.notify_client import NotifyAdminAPIClient, _attach_current_user, cache
|
||||||
|
|
||||||
# from notifications_utils.clients.redis import daily_total_cache_key
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceAPIClient(NotifyAdminAPIClient):
|
class ServiceAPIClient(NotifyAdminAPIClient):
|
||||||
@cache.delete("user-{user_id}")
|
@cache.delete("user-{user_id}")
|
||||||
@@ -497,13 +495,8 @@ class ServiceAPIClient(NotifyAdminAPIClient):
|
|||||||
|
|
||||||
return int(count)
|
return int(count)
|
||||||
|
|
||||||
def get_global_notification_count(self):
|
def get_global_notification_count(self, service_id):
|
||||||
# if cache is not set, or not enabled, return 0
|
return self.get("/service/{}/notification-count".format(service_id))
|
||||||
# TODO FIX
|
|
||||||
# count = redis_client.get(daily_total_cache_key()) or 0
|
|
||||||
|
|
||||||
# return int(count)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
service_api_client = ServiceAPIClient()
|
service_api_client = ServiceAPIClient()
|
||||||
@@ -43,6 +43,11 @@
|
|||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
{% if current_user.platform_admin %}
|
{% if current_user.platform_admin %}
|
||||||
{% set navigation = [
|
{% set navigation = [
|
||||||
|
{
|
||||||
|
"href": url_for("main.show_accounts_or_dashboard"),
|
||||||
|
"text": "Current service",
|
||||||
|
"active": header_navigation.is_selected('accounts-or-dashboard')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"href": url_for('main.get_started'),
|
"href": url_for('main.get_started'),
|
||||||
"text": "Using Notify",
|
"text": "Using Notify",
|
||||||
@@ -75,6 +80,11 @@
|
|||||||
] %}
|
] %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set navigation = [
|
{% set navigation = [
|
||||||
|
{
|
||||||
|
"href": url_for("main.show_accounts_or_dashboard"),
|
||||||
|
"text": "Current service",
|
||||||
|
"active": header_navigation.is_selected('accounts-or-dashboard')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"href": url_for('main.get_started'),
|
"href": url_for('main.get_started'),
|
||||||
"text": "Using Notify",
|
"text": "Using Notify",
|
||||||
@@ -92,7 +102,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": url_for('main.user_profile'),
|
"href": url_for('main.user_profile'),
|
||||||
"text": current_user.name,
|
"text": "User profile",
|
||||||
"active": header_navigation.is_selected('user-profile')
|
"active": header_navigation.is_selected('user-profile')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,16 +4,10 @@
|
|||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-col-8">
|
<div class="grid-col-8">
|
||||||
<h1 class="heading-large">
|
<h1 class="heading-large">
|
||||||
Sorry, there’s a problem with Notify.gov
|
Sorry, we can't deliver what you asked for right now.
|
||||||
</h1>
|
</h1>
|
||||||
<p class="usa-body">
|
<p class="usa-body">
|
||||||
Try again later.
|
Please try again later or <a class="usa-link" href="mailto:notify-support@gsa.gov"></a>email us</a> for more information.</p>
|
||||||
</p>
|
|
||||||
<!-- <p class="usa-body">
|
|
||||||
You can check our <a class="usa-link" href="https://status.notifications.service.gov.uk">system status</a> page to see if there are any known issues.
|
|
||||||
</p> -->
|
|
||||||
<p class="usa-body">
|
|
||||||
To report a problem, please email <a class="usa-link" href="mailto:notify-support@gsa.gov">notify-support@gsa.gov</a>.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
{% if help %}
|
{% if help %}
|
||||||
{% include 'partials/tour.html' %}
|
{% include 'partials/tour.html' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<nav class="nav margin-bottom-5">
|
<nav class="nav">
|
||||||
|
<a class="usa-button margin-top-1 margin-bottom-5 width-full"
|
||||||
|
href="{{ url_for('.choose_template', service_id=current_service.id) }}">Send messages</a>
|
||||||
<ul class="usa-sidenav">
|
<ul class="usa-sidenav">
|
||||||
{% if current_user.has_permissions() %}
|
{% if current_user.has_permissions() %}
|
||||||
{% if current_user.has_permissions('view_activity') %}
|
{% if current_user.has_permissions('view_activity') %}
|
||||||
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('dashboard') }}" href="{{ url_for('.service_dashboard', service_id=current_service.id) }}">Dashboard</a></li>
|
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('dashboard') }}" href="{{ url_for('.service_dashboard', service_id=current_service.id) }}">Dashboard</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('templates') }}" href="{{ url_for('.choose_template', service_id=current_service.id) }}">Send messages</a></li>
|
{# <li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('templates') }}" href="{{ url_for('.choose_template', service_id=current_service.id) }}">Send messages</a></li> #}
|
||||||
{% if not current_user.has_permissions('view_activity') %}
|
{% if not current_user.has_permissions('view_activity') %}
|
||||||
<li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li>
|
<li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -27,8 +29,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div>
|
<div>
|
||||||
<p class="usa--body bold margin-bottom-1">Messages Left Across Services</p>
|
<p class="usa--body bold ">Messages Left Across Services</p>
|
||||||
<p>{{ daily_global_messages_remaining }}</p>
|
<p>{{ daily_global_messages_remaining }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
<div class="navigation-service margin-top-2 display-flex flex-align-end flex-justify border-bottom padding-bottom-1">
|
<div class="navigation-service margin-top-5 display-flex flex-align-end flex-justify border-bottom padding-bottom-1">
|
||||||
{% if current_service.organization_id %}
|
{% if current_service.organization_id %}
|
||||||
{% if current_user.platform_admin or
|
{% if current_user.platform_admin or
|
||||||
(current_user.belongs_to_organization(current_service.organization_id) and current_service.live) %}
|
(current_user.belongs_to_organization(current_service.organization_id) and current_service.live) %}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<h2 class="font-body-lg">Get started</h2>
|
<h2 class="font-body-lg margin-top-0 margin-bottom-1">Get started</h2>
|
||||||
<a class="usa-button" href="{{ url_for('.choose_template', service_id=current_service.id) }}">
|
<a class="usa-button margin-bottom-5" href="{{ url_for('.choose_template', service_id=current_service.id) }}">
|
||||||
Create your first template
|
Create your first template
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
{% from "components/table.html" import mapping_table, row, text_field, optional_text_field, edit_field, field, boolean_field with context %}
|
{% from "components/table.html" import mapping_table, row, text_field, optional_text_field, edit_field, field, boolean_field with context %}
|
||||||
|
|
||||||
{% block per_page_title %}
|
{% block per_page_title %}
|
||||||
Your profile
|
User profile
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block maincolumn_content %}
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
<h1 class="font-body-2xl margin-bottom-3">Your profile</h1>
|
<h1 class="font-body-2xl margin-bottom-3">User profile</h1>
|
||||||
|
|
||||||
<div class="body-copy-table">
|
<div class="body-copy-table">
|
||||||
{% call mapping_table(
|
{% call mapping_table(
|
||||||
caption='Your profile',
|
caption='User profile',
|
||||||
field_headings_visible=False,
|
field_headings_visible=False,
|
||||||
caption_visible=False
|
caption_visible=False
|
||||||
) %}
|
) %}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
{% block beforeContent %}
|
{% block beforeContent %}
|
||||||
{% if current_service and current_service.active and current_user.is_authenticated and current_user.belongs_to_service(current_service.id) %}
|
{% if current_service and current_service.active and current_user.is_authenticated and current_user.belongs_to_service(current_service.id) %}
|
||||||
<div class="navigation-service usa-breadcrumb">
|
<!-- <div class="navigation-service usa-breadcrumb">
|
||||||
<a href="{{ url_for('main.show_accounts_or_dashboard') }}" class="usa-link usa-breadcrumb__link usa-breadcrumb-back-to">Back to {{ current_service.name }}</a>
|
<a href="{{ url_for('main.show_accounts_or_dashboard') }}" class="usa-link usa-breadcrumb__link usa-breadcrumb-back-to">Back to {{ current_service.name }}</a>
|
||||||
</div>
|
</div> -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block backLink %}{% endblock %}
|
{% block backLink %}{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
+23
-1
@@ -1,6 +1,28 @@
|
|||||||
# Notify Sprint Goals Log
|
# Notify Sprint Goals Log
|
||||||
|
|
||||||
## Sprint: T (9/28/23)
|
## Sprint: V (10/30/23)
|
||||||
|
|
||||||
|
| | Goals | Impact |
|
||||||
|
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| Engineering | Continue login.gov [sandbox implementation](https://github.com/GSA/notifications-admin/issues/338), catch up deploys that lag from last week's dependency audit failures, change timezones displays to [Eastern time](https://github.com/GSA/notifications-admin/issues/861), Persist [individal send reports](https://github.com/GSA/notifications-admin/issues/855) somwehere in the app| Stronger auth security, streamlined UX, better timezone familiarity |
|
||||||
|
| UX | Continue making common-sense [UI/UX changes](https://github.com/GSA/notifications-admin/issues/828), review and finalize proposal for [Notify logo](https://github.com/GSA/notifications-admin/issues/859) & begin approvals chain | Improve ease of use, begin process of brand creation |
|
||||||
|
| Security | Complete pre-requisite documentation, start project planning timelines and control group deadlines | Aim to have package completed with enough time to allow for long assessment|
|
||||||
|
| Content | Finalize cloud.gov pages IAA mod for content site | Enable an easy static website for future content |
|
||||||
|
| Ops | Onboard Beverly, get access to tools for them once possible | Add valuable dev resources to increase our capacity
|
||||||
|
|
||||||
|
|
||||||
|
## Sprint: Upupa Marginata (10/12/23)
|
||||||
|
|
||||||
|
| | Goals | Impact |
|
||||||
|
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| Engineering | Shift the quota count from `service` to `org`, complete [notify.gov redirect](https://github.com/GSA/notifications-api/issues/515), continue login.gov [sandbox implementation](https://github.com/GSA/notifications-admin/issues/338), meet with AWS to gain answers on opt-out capabilities| Stronger auth security, streamlined UX, operational efficiency |
|
||||||
|
| UX | Make common-sense [UI/UX changes](https://github.com/GSA/notifications-admin/issues/828), Complete proposal for [Notify logo](https://github.com/GSA/notifications-admin/issues/859), switch application to Eastern timezone displays | Improve ease of use, begin process of brand creation |
|
||||||
|
| Security | Complete pre-requisite documentation, start project planning timelines and control group deadlines | Aim to have package completed with enough time to allow for long assessment|
|
||||||
|
| Content | Work on cloud.gov pages IAA mod for content site | Enable an easy static website for future content |
|
||||||
|
| Ops | Onboard new back-end dev, get access to tools for them once possible | Add valuable dev resources to increase our capacity
|
||||||
|
|
||||||
|
|
||||||
|
## Sprint: Toucan (9/28/23)
|
||||||
|
|
||||||
| | Goals | Impact |
|
| | Goals | Impact |
|
||||||
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
|||||||
Generated
+23
-23
@@ -118,12 +118,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.22.15",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||||
"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
|
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.22.15",
|
"@babel/types": "^7.23.0",
|
||||||
"@jridgewell/gen-mapping": "^0.3.2",
|
"@jridgewell/gen-mapping": "^0.3.2",
|
||||||
"@jridgewell/trace-mapping": "^0.3.17",
|
"@jridgewell/trace-mapping": "^0.3.17",
|
||||||
"jsesc": "^2.5.1"
|
"jsesc": "^2.5.1"
|
||||||
@@ -239,13 +239,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-function-name": {
|
"node_modules/@babel/helper-function-name": {
|
||||||
"version": "7.22.5",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||||
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
|
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.22.5",
|
"@babel/template": "^7.22.15",
|
||||||
"@babel/types": "^7.22.5"
|
"@babel/types": "^7.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -467,9 +467,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.22.16",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||||
"integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
|
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@@ -1682,19 +1682,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.22.20",
|
"version": "7.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||||
"integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==",
|
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.22.13",
|
"@babel/code-frame": "^7.22.13",
|
||||||
"@babel/generator": "^7.22.15",
|
"@babel/generator": "^7.23.0",
|
||||||
"@babel/helper-environment-visitor": "^7.22.20",
|
"@babel/helper-environment-visitor": "^7.22.20",
|
||||||
"@babel/helper-function-name": "^7.22.5",
|
"@babel/helper-function-name": "^7.23.0",
|
||||||
"@babel/helper-hoist-variables": "^7.22.5",
|
"@babel/helper-hoist-variables": "^7.22.5",
|
||||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||||
"@babel/parser": "^7.22.16",
|
"@babel/parser": "^7.23.0",
|
||||||
"@babel/types": "^7.22.19",
|
"@babel/types": "^7.23.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
},
|
},
|
||||||
@@ -1703,13 +1703,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.22.19",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||||
"integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==",
|
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.22.5",
|
"@babel/helper-string-parser": "^7.22.5",
|
||||||
"@babel/helper-validator-identifier": "^7.22.19",
|
"@babel/helper-validator-identifier": "^7.22.20",
|
||||||
"to-fast-properties": "^2.0.0"
|
"to-fast-properties": "^2.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
Generated
+46
-35
@@ -142,13 +142,13 @@ css = ["tinycss2 (>=1.1.0,<1.3)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blinker"
|
name = "blinker"
|
||||||
version = "1.6.3"
|
version = "1.7.0"
|
||||||
description = "Fast, simple object-to-object and broadcast signaling"
|
description = "Fast, simple object-to-object and broadcast signaling"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "blinker-1.6.3-py3-none-any.whl", hash = "sha256:296320d6c28b006eb5e32d4712202dbcdcbf5dc482da298c2f44881c43884aaa"},
|
{file = "blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9"},
|
||||||
{file = "blinker-1.6.3.tar.gz", hash = "sha256:152090d27c1c5c722ee7e48504b02d76502811ce02e1523553b4cf8c8b3d3a8d"},
|
{file = "blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1388,6 +1388,16 @@ files = [
|
|||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
|
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
|
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
|
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
|
||||||
|
{file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
|
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
|
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
|
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
|
||||||
@@ -1580,26 +1590,26 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "newrelic"
|
name = "newrelic"
|
||||||
version = "9.1.0"
|
version = "9.1.1"
|
||||||
description = "New Relic Python Agent"
|
description = "New Relic Python Agent"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
||||||
files = [
|
files = [
|
||||||
{file = "newrelic-9.1.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:1e9ede0fd193b0fec7b0a1b55b8bd81bc51151f80046309a999b3939c32e5820"},
|
{file = "newrelic-9.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:639abcaa1baee5a1a137036e328617e3a6bbb33a63814ef6227a8059d9062f0d"},
|
||||||
{file = "newrelic-9.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:08d4b93d3c60518bacd8e69e76dfe488980ab71a74fab24c9a23f429b067c2d5"},
|
{file = "newrelic-9.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:1bd46363c71c3fc5dbcc0e96e1698757f4e7ff82c73a0ccb28f18c2b9f9c5de5"},
|
||||||
{file = "newrelic-9.1.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:434c2a876223daaeb8c1db46cb399319b5f4d554002f17f51572888b35a4a577"},
|
{file = "newrelic-9.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:fbebaf8d9801eef85827ca2906a7bdbc2a458a226455da49c71857e2ce2b264a"},
|
||||||
{file = "newrelic-9.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4505991bc0e0554482ed4b7cd94486ade521cc7408870f1c89d7b4d65c7ff532"},
|
{file = "newrelic-9.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:c1a91322fdb301a7a17aab8df2e70925c1e2a01a61136d86a0e433f6ff167c5c"},
|
||||||
{file = "newrelic-9.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c92458b80c9a0841acdd50db7a5ba3b6b8d35b2859b0f3c907d2f01a90b6b0e5"},
|
{file = "newrelic-9.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d677f8f11bd69d92a4b359c53a04e02094e5198ed1aa49c9b1ca235522d5efd5"},
|
||||||
{file = "newrelic-9.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b475ec4b1ac7e7026d7e23d63e6fff2db0c8b5d720f6603faddf78f833459966"},
|
{file = "newrelic-9.1.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:289cebbb86eb92b6c133e18cd5640115a918db41ae791d11c1ded5b592dd7c23"},
|
||||||
{file = "newrelic-9.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bdcf45a4074b49daabb0e89378f83577dee1aa645ae9b34b86234d8755f3454"},
|
{file = "newrelic-9.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1b93effe99be14a1747a70e9368274091abbed2ef3c593b08a29732d72d83e4"},
|
||||||
{file = "newrelic-9.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f0add508afc0195631a2d91fd267fe8f63e153b633ec4503edef5019868a762"},
|
{file = "newrelic-9.1.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45966c5f083d1f1abb76828c4864d20296f6929053fbe4d122e164d84c78e388"},
|
||||||
{file = "newrelic-9.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7aefddec021b1259317e03ddaa6945e0562e96742b79be4f04a6ab845b88121"},
|
{file = "newrelic-9.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18e8e6af37cc084007913b991bced2ea2b8b31ed5318a397f210a9625c214459"},
|
||||||
{file = "newrelic-9.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf178086cf1a5d1fcfeedff871968c7c0a70f677c84afc6cc2f6ccb6430f3f83"},
|
{file = "newrelic-9.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:437dfae553012dbe6e0f288b1f600ef27b0ebc2c367641723529b1a71fa541ae"},
|
||||||
{file = "newrelic-9.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52c690d9529d208446c0861f28be0b8056e1e5004246b312fb7af59c9f45f694"},
|
{file = "newrelic-9.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5489becb7cff1ba992405c9d891fd1743e8042910c97f89ac072fd562501cdb1"},
|
||||||
{file = "newrelic-9.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a4b602b131aa7e0795f08a8ec0d1adc5361542222927c156f9a1e8b1eecd09f"},
|
{file = "newrelic-9.1.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8403b48807eae524ee1b2da254f4222834f3aef8326dd4475f0b22f924774bde"},
|
||||||
{file = "newrelic-9.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:427f8266a450f295b6d28127070a07937946392d433a05ab81528cbe5aae9f51"},
|
{file = "newrelic-9.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:603158cb23ed6604845e4fc8ee2a052e60003ccbb7da0f4b00667cd0c7c77c11"},
|
||||||
{file = "newrelic-9.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:098717a64be932c70a6145f15a4b73416613bf00b14452b73ef7bae89888475b"},
|
{file = "newrelic-9.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96dedf6c1a385bf7b4b1336b3e4b5a0d6e983b5305022176c7c43d327e768bf3"},
|
||||||
{file = "newrelic-9.1.0.tar.gz", hash = "sha256:29032d57a41b03ff028c5dd7173491f7e21743ed9444f693e0b662007eee3d6a"},
|
{file = "newrelic-9.1.1.tar.gz", hash = "sha256:968a3662ccfb881498789105a52eec866b57c22b8cbdef43889ad76881c62a95"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@@ -1607,12 +1617,12 @@ infinite-tracing = ["grpcio", "protobuf"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notifications-python-client"
|
name = "notifications-python-client"
|
||||||
version = "8.0.1"
|
version = "8.1.0"
|
||||||
description = "Python API client for GOV.UK Notify."
|
description = "Python API client for GOV.UK Notify."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "notifications_python_client-8.0.1-py3-none-any.whl", hash = "sha256:e89f5ad7caf17065ede88a1c2270c32cc24de75843856e524a2336f952260b4c"},
|
{file = "notifications_python_client-8.1.0-py3-none-any.whl", hash = "sha256:8aec1f7a4ba592fd699eae899df8ccca9ccafb614f47826c07b318ca903c9c13"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -2203,20 +2213,21 @@ requests = ">=2.9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-env"
|
name = "pytest-env"
|
||||||
version = "1.0.1"
|
version = "1.1.1"
|
||||||
description = "py.test plugin that allows you to add environment variables."
|
description = "pytest plugin that allows you to add environment variables."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "pytest_env-1.0.1-py3-none-any.whl", hash = "sha256:e8faf927c6fcdbbc8fe3317506acc116713c9708d01652a0fd945f9ae27b71aa"},
|
{file = "pytest_env-1.1.1-py3-none-any.whl", hash = "sha256:2b71b37c6810f28bec790a7b373c777af87352b3a359b3de0edb9d24df5cf8b3"},
|
||||||
{file = "pytest_env-1.0.1.tar.gz", hash = "sha256:603fe216e8e03a5d134989cb41317c59aabef013d2250c71b864ab0798fbe6f6"},
|
{file = "pytest_env-1.1.1.tar.gz", hash = "sha256:1efb8acce1f6431196150f3b30673443ff05a6fabff64539a9495cd2248adf9e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pytest = ">=7.3.1"
|
pytest = ">=7.4.3"
|
||||||
|
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
test = ["coverage (>=7.2.7)", "pytest-mock (>=3.10)"]
|
test = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "pytest-mock (>=3.12)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-mock"
|
name = "pytest-mock"
|
||||||
@@ -2888,17 +2899,17 @@ watchdog = ["watchdog (>=2.3)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wtforms"
|
name = "wtforms"
|
||||||
version = "3.0.1"
|
version = "3.1.1"
|
||||||
description = "Form validation and rendering for Python web development."
|
description = "Form validation and rendering for Python web development."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "WTForms-3.0.1-py3-none-any.whl", hash = "sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b"},
|
{file = "wtforms-3.1.1-py3-none-any.whl", hash = "sha256:ae7c54b29806c70f7bce8eb9f24afceb10ca5c32af3d9f04f74d2f66ccc5c7e0"},
|
||||||
{file = "WTForms-3.0.1.tar.gz", hash = "sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc"},
|
{file = "wtforms-3.1.1.tar.gz", hash = "sha256:5e51df8af9a60f6beead75efa10975e97768825a82146a65c7cbf5b915990620"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
MarkupSafe = "*"
|
markupsafe = "*"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
email = ["email-validator"]
|
email = ["email-validator"]
|
||||||
@@ -2959,4 +2970,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,<3.12"
|
python-versions = ">=3.9,<3.12"
|
||||||
content-hash = "aaa7d5312bcb253901fe986e5a59f5a4de4aff94216b0d8251fe517113a24d15"
|
content-hash = "dc52fb7e5db480267e4f6102edee0ce19669cfd853b8b32e6758366b5e048021"
|
||||||
+4
-5
@@ -8,7 +8,7 @@ readme = "README.md"
|
|||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = ">=3.9,<3.12"
|
python = ">=3.9,<3.12"
|
||||||
ago = "~=0.0.95"
|
ago = "~=0.0.95"
|
||||||
blinker = "~=1.6"
|
blinker = "~=1.7"
|
||||||
exceptiongroup = "==1.1.3"
|
exceptiongroup = "==1.1.3"
|
||||||
flask = "~=2.3"
|
flask = "~=2.3"
|
||||||
flask-basicauth = "~=0.2"
|
flask-basicauth = "~=0.2"
|
||||||
@@ -22,21 +22,20 @@ humanize = "~=4.8"
|
|||||||
itsdangerous = "~=2.1"
|
itsdangerous = "~=2.1"
|
||||||
jinja2 = "~=3.1"
|
jinja2 = "~=3.1"
|
||||||
newrelic = "*"
|
newrelic = "*"
|
||||||
notifications-python-client = "==8.0.1"
|
notifications-python-client = "==8.1.0"
|
||||||
notifications-utils = {git = "https://github.com/GSA/notifications-utils.git"}
|
notifications-utils = {git = "https://github.com/GSA/notifications-utils.git"}
|
||||||
pyexcel = "==0.7.0"
|
pyexcel = "==0.7.0"
|
||||||
pyexcel-io = "==0.6.6"
|
pyexcel-io = "==0.6.6"
|
||||||
pyexcel-ods3 = "==0.6.1"
|
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"
|
||||||
pyjwt = "^2.8.0"
|
|
||||||
openpyxl = "==3.0.10"
|
openpyxl = "==3.0.10"
|
||||||
pyproj = "==3.6.1"
|
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"
|
||||||
werkzeug = "^3.0.1"
|
werkzeug = "^3.0.1"
|
||||||
wtforms = "~=3.0"
|
wtforms = "~=3.1"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
@@ -54,7 +53,7 @@ jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
|
|||||||
moto = "^4.2"
|
moto = "^4.2"
|
||||||
pip-audit = "*"
|
pip-audit = "*"
|
||||||
pytest = "^7.4.3"
|
pytest = "^7.4.3"
|
||||||
pytest-env = "^1.0.1"
|
pytest-env = "^1.1.1"
|
||||||
pytest-mock = "^3.12.0"
|
pytest-mock = "^3.12.0"
|
||||||
pytest-playwright = "^0.4.3"
|
pytest-playwright = "^0.4.3"
|
||||||
pytest-xdist = "^3.3.1"
|
pytest-xdist = "^3.3.1"
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ class TestAssetFingerprint(object):
|
|||||||
asset_fingerprinter = AssetFingerprinter(asset_root="/suppliers/static/")
|
asset_fingerprinter = AssetFingerprinter(asset_root="/suppliers/static/")
|
||||||
assert (
|
assert (
|
||||||
asset_fingerprinter.get_url("application.css")
|
asset_fingerprinter.get_url("application.css")
|
||||||
== "/suppliers/static/application.css?418e6f4a6cdf1142e45c072ed3e1c90a" # noqa
|
== "/suppliers/static/application.css?418e6f4a6cdf1142e45c072ed3e1c90a"
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
asset_fingerprinter.get_url("application-ie6.css")
|
asset_fingerprinter.get_url("application-ie6.css")
|
||||||
== "/suppliers/static/application-ie6.css?418e6f4a6cdf1142e45c072ed3e1c90a" # noqa
|
== "/suppliers/static/application-ie6.css?418e6f4a6cdf1142e45c072ed3e1c90a"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_building_file_path(self, mocker):
|
def test_building_file_path(self, mocker):
|
||||||
|
|||||||
@@ -54,7 +54,10 @@ def test_csrf_returns_400(client_request, mocker):
|
|||||||
_test_page_title=False,
|
_test_page_title=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert page.h1.string.strip() == "Sorry, there’s a problem with Notify.gov"
|
assert (
|
||||||
|
page.h1.string.strip()
|
||||||
|
== "Sorry, we can't deliver what you asked for right now."
|
||||||
|
)
|
||||||
assert (
|
assert (
|
||||||
page.title.string.strip()
|
page.title.string.strip()
|
||||||
== "Sorry, there’s a problem with the service – Notify.gov"
|
== "Sorry, there’s a problem with the service – Notify.gov"
|
||||||
@@ -75,7 +78,10 @@ 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):
|
def test_405_returns_something_went_wrong_page(client_request, mocker):
|
||||||
page = client_request.post_url("/", _expected_status=405)
|
page = client_request.post_url("/", _expected_status=405)
|
||||||
|
|
||||||
assert page.h1.string.strip() == "Sorry, there’s a problem with Notify.gov"
|
assert (
|
||||||
|
page.h1.string.strip()
|
||||||
|
== "Sorry, we can't deliver what you asked for right now."
|
||||||
|
)
|
||||||
assert (
|
assert (
|
||||||
page.title.string.strip()
|
page.title.string.strip()
|
||||||
== "Sorry, there’s a problem with the service – Notify.gov"
|
== "Sorry, there’s a problem with the service – Notify.gov"
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ def test_service_navigation_for_org_user(
|
|||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
)
|
)
|
||||||
assert [item.text.strip() for item in page.select("nav.nav a")] == [
|
assert [item.text.strip() for item in page.select("nav.nav a")] == [
|
||||||
|
"Send messages",
|
||||||
"Usage",
|
"Usage",
|
||||||
"Team members",
|
"Team members",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -256,21 +256,23 @@ def test_choose_account_should_should_organizations_link_for_platform_admin(
|
|||||||
] == expected_headings
|
] == expected_headings
|
||||||
|
|
||||||
|
|
||||||
def test_choose_account_should_show_back_to_service_link(
|
# Moving the back to service link into the top navigation
|
||||||
client_request,
|
|
||||||
mock_get_orgs_and_services,
|
|
||||||
mock_get_organization,
|
|
||||||
mock_get_organization_services,
|
|
||||||
):
|
|
||||||
resp = client_request.get("main.choose_account")
|
|
||||||
|
|
||||||
service_navigation = resp.find(
|
# def test_choose_account_should_show_back_to_service_link(
|
||||||
"div", {"class": "navigation-service usa-breadcrumb"}
|
# client_request,
|
||||||
)
|
# mock_get_orgs_and_services,
|
||||||
back_to_service_link = service_navigation.a
|
# mock_get_organization,
|
||||||
|
# mock_get_organization_services,
|
||||||
|
# ):
|
||||||
|
# resp = client_request.get("main.choose_account")
|
||||||
|
|
||||||
assert back_to_service_link["href"] == url_for("main.show_accounts_or_dashboard")
|
# service_navigation = resp.find(
|
||||||
assert back_to_service_link.text == "Back to service one"
|
# "div", {"class": "navigation-service usa-breadcrumb"}
|
||||||
|
# )
|
||||||
|
# back_to_service_link = service_navigation.a
|
||||||
|
|
||||||
|
# assert back_to_service_link["href"] == url_for("main.show_accounts_or_dashboard")
|
||||||
|
# assert back_to_service_link.text == "Back to service one"
|
||||||
|
|
||||||
|
|
||||||
def test_choose_account_should_not_show_back_to_service_link_if_no_service_in_session(
|
def test_choose_account_should_not_show_back_to_service_link_if_no_service_in_session(
|
||||||
@@ -322,7 +324,7 @@ def test_choose_account_should_not_show_back_to_service_link_if_service_archived
|
|||||||
|
|
||||||
assert normalize_spaces(page.select_one("h1").text) == "Choose service"
|
assert normalize_spaces(page.select_one("h1").text) == "Choose service"
|
||||||
if active:
|
if active:
|
||||||
assert page.select_one(".navigation-service a") is not None
|
assert page.select_one(".navigation-service a") is None
|
||||||
else:
|
else:
|
||||||
assert page.select_one(".navigation-service a") is None
|
assert page.select_one(".navigation-service a") is None
|
||||||
|
|
||||||
@@ -361,7 +363,7 @@ def test_should_show_back_to_service_if_user_belongs_to_service(
|
|||||||
):
|
):
|
||||||
mock_get_service.return_value = service_one
|
mock_get_service.return_value = service_one
|
||||||
expected_page_text = (
|
expected_page_text = (
|
||||||
"Test Service Switch service " "" "Dashboard " "Send messages " "Team members"
|
"Test Service Switch service " "Send messages " "Dashboard " "Team members"
|
||||||
) # TODO: set sidebar variables in common test module
|
) # TODO: set sidebar variables in common test module
|
||||||
|
|
||||||
page = client_request.get(
|
page = client_request.get(
|
||||||
|
|||||||
@@ -190,12 +190,10 @@ def test_service_setting_link_toggles_index_error(
|
|||||||
index,
|
index,
|
||||||
text,
|
text,
|
||||||
):
|
):
|
||||||
with pytest.raises( # noqa: PT012 # Requires more research to refactor.
|
url_for(endpoint, service_id=service_one["id"])
|
||||||
expected_exception=IndexError
|
service_one.update(service_fields)
|
||||||
):
|
page = get_service_settings_page()
|
||||||
url_for(endpoint, service_id=service_one["id"])
|
with pytest.raises(expected_exception=IndexError):
|
||||||
service_one.update(service_fields)
|
|
||||||
page = get_service_settings_page()
|
|
||||||
page.select(".page-footer-link a")[index]
|
page.select(".page-footer-link a")[index]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -744,13 +744,11 @@ def test_should_check_for_reply_to_on_go_live_index_error(
|
|||||||
return_value=volume,
|
return_value=volume,
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises( # noqa: PT012 # This will require more research for refactoring.
|
page = client_request.get("main.request_to_go_live", service_id=SERVICE_ONE_ID)
|
||||||
expected_exception=IndexError
|
assert page.h1.text == "Before you request to go live"
|
||||||
):
|
checklist_items = page.select(".task-list .task-list-item")
|
||||||
page = client_request.get("main.request_to_go_live", service_id=SERVICE_ONE_ID)
|
|
||||||
assert page.h1.text == "Before you request to go live"
|
|
||||||
|
|
||||||
checklist_items = page.select(".task-list .task-list-item")
|
with pytest.raises(expected_exception=IndexError):
|
||||||
assert (
|
assert (
|
||||||
normalize_spaces(checklist_items[3].text)
|
normalize_spaces(checklist_items[3].text)
|
||||||
== expected_reply_to_checklist_item
|
== expected_reply_to_checklist_item
|
||||||
@@ -1030,19 +1028,24 @@ def test_should_check_for_sms_sender_on_go_live(
|
|||||||
return_value=volume,
|
return_value=volume,
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises( # noqa: PT012 # Requires more research for how to refactor.
|
with pytest.raises(expected_exception=IndexError):
|
||||||
expected_exception=IndexError
|
simple_statement_for_test_should_check_for_sms_sender_on_go_live(
|
||||||
):
|
client_request, expected_sms_sender_checklist_item, mock_get_sms_senders
|
||||||
page = client_request.get("main.request_to_go_live", service_id=SERVICE_ONE_ID)
|
|
||||||
assert page.h1.text == "Before you request to go live"
|
|
||||||
|
|
||||||
checklist_items = page.select(".task-list .task-list-item")
|
|
||||||
assert (
|
|
||||||
normalize_spaces(checklist_items[3].text)
|
|
||||||
== expected_sms_sender_checklist_item
|
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_get_sms_senders.assert_called_once_with(SERVICE_ONE_ID)
|
|
||||||
|
def simple_statement_for_test_should_check_for_sms_sender_on_go_live(
|
||||||
|
client_request, expected_sms_sender_checklist_item, mock_get_sms_senders
|
||||||
|
):
|
||||||
|
page = client_request.get("main.request_to_go_live", service_id=SERVICE_ONE_ID)
|
||||||
|
assert page.h1.text == "Before you request to go live"
|
||||||
|
checklist_items = page.select(".task-list .task-list-item")
|
||||||
|
|
||||||
|
assert (
|
||||||
|
normalize_spaces(checklist_items[3].text) == expected_sms_sender_checklist_item
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_get_sms_senders.assert_called_once_with(SERVICE_ONE_ID)
|
||||||
|
|
||||||
|
|
||||||
def test_non_gov_user_is_told_they_cant_go_live(
|
def test_non_gov_user_is_told_they_cant_go_live(
|
||||||
@@ -3145,10 +3148,8 @@ def test_should_set_sms_allowance_fails(
|
|||||||
mock_get_free_sms_fragment_limit,
|
mock_get_free_sms_fragment_limit,
|
||||||
mock_create_or_update_free_sms_fragment_limit,
|
mock_create_or_update_free_sms_fragment_limit,
|
||||||
):
|
):
|
||||||
with pytest.raises( # noqa: PT012 # Needs more research for refactoring.
|
client_request.login(platform_admin_user)
|
||||||
expected_exception=AssertionError
|
with pytest.raises(expected_exception=AssertionError):
|
||||||
):
|
|
||||||
client_request.login(platform_admin_user)
|
|
||||||
client_request.post(
|
client_request.post(
|
||||||
"main.set_free_sms_allowance",
|
"main.set_free_sms_allowance",
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
@@ -3460,10 +3461,8 @@ def test_archive_service_after_confirm_error(
|
|||||||
mocker.patch("app.notify_client.service_api_client.redis_client.delete")
|
mocker.patch("app.notify_client.service_api_client.redis_client.delete")
|
||||||
mocker.patch("app.notify_client.service_api_client.redis_client.delete_by_pattern")
|
mocker.patch("app.notify_client.service_api_client.redis_client.delete_by_pattern")
|
||||||
|
|
||||||
with pytest.raises( # noqa: PT012 # Needs more research for refactoring.
|
client_request.login(user)
|
||||||
expected_exception=AssertionError
|
with pytest.raises(expected_exception=AssertionError):
|
||||||
):
|
|
||||||
client_request.login(user)
|
|
||||||
client_request.post(
|
client_request.post(
|
||||||
"main.archive_service",
|
"main.archive_service",
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
@@ -3596,10 +3595,8 @@ def test_suspend_service_after_confirm_error(
|
|||||||
):
|
):
|
||||||
mocker.patch("app.service_api_client.post")
|
mocker.patch("app.service_api_client.post")
|
||||||
mocker.patch("app.main.views.service_settings.create_suspend_service_event")
|
mocker.patch("app.main.views.service_settings.create_suspend_service_event")
|
||||||
with pytest.raises( # noqa: PT012 # Needs more research for refactoring.
|
client_request.login(user)
|
||||||
expected_exception=AssertionError
|
with pytest.raises(expected_exception=AssertionError):
|
||||||
):
|
|
||||||
client_request.login(user)
|
|
||||||
client_request.post(
|
client_request.post(
|
||||||
"main.suspend_service",
|
"main.suspend_service",
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
|
|||||||
@@ -321,6 +321,14 @@ def test_route_permissions(
|
|||||||
route,
|
route,
|
||||||
):
|
):
|
||||||
with notify_admin.test_request_context():
|
with notify_admin.test_request_context():
|
||||||
|
|
||||||
|
def _get(mocker):
|
||||||
|
return {"count": 0}
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
"app.service_api_client.get_global_notification_count", side_effect=_get
|
||||||
|
)
|
||||||
|
|
||||||
validate_route_permission(
|
validate_route_permission(
|
||||||
mocker,
|
mocker,
|
||||||
notify_admin,
|
notify_admin,
|
||||||
@@ -346,6 +354,14 @@ def test_route_invalid_permissions(
|
|||||||
route,
|
route,
|
||||||
):
|
):
|
||||||
with notify_admin.test_request_context():
|
with notify_admin.test_request_context():
|
||||||
|
|
||||||
|
def _get(mocker):
|
||||||
|
return {"count": 0}
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
"app.service_api_client.get_global_notification_count", side_effect=_get
|
||||||
|
)
|
||||||
|
|
||||||
validate_route_permission(
|
validate_route_permission(
|
||||||
mocker,
|
mocker,
|
||||||
notify_admin,
|
notify_admin,
|
||||||
|
|||||||
@@ -1174,6 +1174,14 @@ def test_route_for_service_permissions(
|
|||||||
mock_get_inbound_sms_summary,
|
mock_get_inbound_sms_summary,
|
||||||
):
|
):
|
||||||
with notify_admin.test_request_context():
|
with notify_admin.test_request_context():
|
||||||
|
|
||||||
|
def _get(mocker):
|
||||||
|
return {"count": 0}
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
"app.service_api_client.get_global_notification_count", side_effect=_get
|
||||||
|
)
|
||||||
|
|
||||||
validate_route_permission(
|
validate_route_permission(
|
||||||
mocker,
|
mocker,
|
||||||
notify_admin,
|
notify_admin,
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ def test_owasp_useful_headers_set(
|
|||||||
assert search(r"frame-ancestors 'none';", csp)
|
assert search(r"frame-ancestors 'none';", csp)
|
||||||
assert search(r"form-action 'self';", csp)
|
assert search(r"form-action 'self';", csp)
|
||||||
assert search(
|
assert search(
|
||||||
r"script-src 'self' static\.example\.com 'unsafe-eval' https:\/\/js-agent\.newrelic\.com https:\/\/gov-bam\.nr-data\.net 'nonce-.*';", # noqa e501
|
r"script-src 'self' static\.example\.com 'unsafe-eval' https:\/\/js-agent\.new"
|
||||||
|
r"relic\.com https:\/\/gov-bam\.nr-data\.net 'nonce-.*';",
|
||||||
csp,
|
csp,
|
||||||
)
|
)
|
||||||
assert search(r"connect-src 'self' https:\/\/gov-bam.nr-data\.net;", csp)
|
assert search(r"connect-src 'self' https:\/\/gov-bam.nr-data\.net;", csp)
|
||||||
|
|||||||
@@ -238,7 +238,8 @@ def test_should_show_job_with_sending_limit_exceeded_status(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert normalize_spaces(page.select("main p")[1].text) == (
|
assert normalize_spaces(page.select("main p")[1].text) == (
|
||||||
"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
|
"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."
|
||||||
)
|
)
|
||||||
assert normalize_spaces(page.select("main p")[2].text) == (
|
assert normalize_spaces(page.select("main p")[2].text) == (
|
||||||
"Upload this spreadsheet again tomorrow or contact the Notify.gov team to raise the limit."
|
"Upload this spreadsheet again tomorrow or contact the Notify.gov team to raise the limit."
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ from tests.conftest import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize( # noqa: PT014 # Duplicate parameters have different permissions.
|
@pytest.mark.parametrize(
|
||||||
("user", "expected_self_text", "expected_coworker_text"),
|
("user", "expected_self_text", "add_details"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
create_active_user_with_permissions(),
|
create_active_user_with_permissions(),
|
||||||
@@ -34,16 +34,7 @@ from tests.conftest import (
|
|||||||
"Can Manage settings, team and usage "
|
"Can Manage settings, team and usage "
|
||||||
"Can Manage API integration"
|
"Can Manage API integration"
|
||||||
),
|
),
|
||||||
(
|
True,
|
||||||
"ZZZZZZZZ zzzzzzz@example.gsa.gov "
|
|
||||||
"Permissions "
|
|
||||||
"Can See dashboard "
|
|
||||||
"Cannot Send messages "
|
|
||||||
"Cannot Add and edit templates "
|
|
||||||
"Cannot Manage settings, team and usage "
|
|
||||||
"Cannot Manage API integration "
|
|
||||||
"Change details for ZZZZZZZZ zzzzzzz@example.gsa.gov"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
create_active_user_empty_permissions(),
|
create_active_user_empty_permissions(),
|
||||||
@@ -56,15 +47,7 @@ from tests.conftest import (
|
|||||||
"Cannot Manage settings, team and usage "
|
"Cannot Manage settings, team and usage "
|
||||||
"Cannot Manage API integration"
|
"Cannot Manage API integration"
|
||||||
),
|
),
|
||||||
(
|
False,
|
||||||
"ZZZZZZZZ zzzzzzz@example.gsa.gov "
|
|
||||||
"Permissions "
|
|
||||||
"Can See dashboard "
|
|
||||||
"Cannot Send messages "
|
|
||||||
"Cannot Add and edit templates "
|
|
||||||
"Cannot Manage settings, team and usage "
|
|
||||||
"Cannot Manage API integration"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
create_active_user_view_permissions(),
|
create_active_user_view_permissions(),
|
||||||
@@ -77,15 +60,7 @@ from tests.conftest import (
|
|||||||
"Cannot Manage settings, team and usage "
|
"Cannot Manage settings, team and usage "
|
||||||
"Cannot Manage API integration"
|
"Cannot Manage API integration"
|
||||||
),
|
),
|
||||||
(
|
False,
|
||||||
"ZZZZZZZZ zzzzzzz@example.gsa.gov "
|
|
||||||
"Permissions "
|
|
||||||
"Can See dashboard "
|
|
||||||
"Cannot Send messages "
|
|
||||||
"Cannot Add and edit templates "
|
|
||||||
"Cannot Manage settings, team and usage "
|
|
||||||
"Cannot Manage API integration"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
create_active_user_manage_template_permissions(),
|
create_active_user_manage_template_permissions(),
|
||||||
@@ -98,36 +73,7 @@ from tests.conftest import (
|
|||||||
"Cannot Manage settings, team and usage "
|
"Cannot Manage settings, team and usage "
|
||||||
"Cannot Manage API integration"
|
"Cannot Manage API integration"
|
||||||
),
|
),
|
||||||
(
|
False,
|
||||||
"ZZZZZZZZ zzzzzzz@example.gsa.gov "
|
|
||||||
"Permissions "
|
|
||||||
"Can See dashboard "
|
|
||||||
"Cannot Send messages "
|
|
||||||
"Cannot Add and edit templates "
|
|
||||||
"Cannot Manage settings, team and usage "
|
|
||||||
"Cannot Manage API integration"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
create_active_user_manage_template_permissions(),
|
|
||||||
(
|
|
||||||
"Test User With Permissions (you) "
|
|
||||||
"Permissions "
|
|
||||||
"Can See dashboard "
|
|
||||||
"Cannot Send messages "
|
|
||||||
"Can Add and edit templates "
|
|
||||||
"Cannot Manage settings, team and usage "
|
|
||||||
"Cannot Manage API integration"
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"ZZZZZZZZ zzzzzzz@example.gsa.gov "
|
|
||||||
"Permissions "
|
|
||||||
"Can See dashboard "
|
|
||||||
"Cannot Send messages "
|
|
||||||
"Cannot Add and edit templates "
|
|
||||||
"Cannot Manage settings, team and usage "
|
|
||||||
"Cannot Manage API integration"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -140,8 +86,8 @@ def test_should_show_overview_page(
|
|||||||
service_one,
|
service_one,
|
||||||
user,
|
user,
|
||||||
expected_self_text,
|
expected_self_text,
|
||||||
expected_coworker_text,
|
|
||||||
active_user_view_permissions,
|
active_user_view_permissions,
|
||||||
|
add_details,
|
||||||
):
|
):
|
||||||
current_user = user
|
current_user = user
|
||||||
other_user = copy.deepcopy(active_user_view_permissions)
|
other_user = copy.deepcopy(active_user_view_permissions)
|
||||||
@@ -164,11 +110,20 @@ def test_should_show_overview_page(
|
|||||||
assert (
|
assert (
|
||||||
normalize_spaces(page.select(".user-list-item")[0].text) == expected_self_text
|
normalize_spaces(page.select(".user-list-item")[0].text) == expected_self_text
|
||||||
)
|
)
|
||||||
# [1:5] are invited users
|
|
||||||
assert (
|
expected = (
|
||||||
normalize_spaces(page.select(".user-list-item")[6].text)
|
"ZZZZZZZZ zzzzzzz@example.gsa.gov "
|
||||||
== expected_coworker_text
|
"Permissions "
|
||||||
|
"Can See dashboard "
|
||||||
|
"Cannot Send messages "
|
||||||
|
"Cannot Add and edit templates "
|
||||||
|
"Cannot Manage settings, team and usage "
|
||||||
|
"Cannot Manage API integration"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if add_details is True:
|
||||||
|
expected = f"{expected} Change details for ZZZZZZZZ zzzzzzz@example.gsa.gov"
|
||||||
|
assert normalize_spaces(page.select(".user-list-item")[6].text) == expected
|
||||||
mock_get_users.assert_called_once_with(SERVICE_ONE_ID)
|
mock_get_users.assert_called_once_with(SERVICE_ONE_ID)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -770,10 +770,12 @@ def test_clear_cache_shows_form(
|
|||||||
[
|
[
|
||||||
call("service-????????-????-????-????-????????????-templates"),
|
call("service-????????-????-????-????-????????????-templates"),
|
||||||
call(
|
call(
|
||||||
"service-????????-????-????-????-????????????-template-????????-????-????-????-????????????-version-*" # noqa
|
"service-????????-????-????-????-????????????-template"
|
||||||
|
"-????????-????-????-????-????????????-version-*"
|
||||||
),
|
),
|
||||||
call(
|
call(
|
||||||
"service-????????-????-????-????-????????????-template-????????-????-????-????-????????????-versions" # noqa
|
"service-????????-????-????-????-????????????-template"
|
||||||
|
"-????????-????-????-????-????????????-versions"
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
"Removed 6 objects across 3 key formats for template",
|
"Removed 6 objects across 3 key formats for template",
|
||||||
|
|||||||
@@ -2319,25 +2319,31 @@ def test_warns_if_file_sent_already_errors(
|
|||||||
"app.main.views.send.get_csv_metadata",
|
"app.main.views.send.get_csv_metadata",
|
||||||
return_value={"original_file_name": uploaded_file_name},
|
return_value={"original_file_name": uploaded_file_name},
|
||||||
)
|
)
|
||||||
# Should be botocore.errorfactory.NoSuchKey but for some reason can't use that
|
|
||||||
with pytest.raises( # noqa: PT011,PT012 # Requires more research on how to refactor.
|
with pytest.raises(
|
||||||
expected_exception=Exception
|
expected_exception=Exception, match="Unable to locate credentials"
|
||||||
):
|
):
|
||||||
page = client_request.get(
|
stmt_for_test_warns_if_file_sent_already_errors(
|
||||||
"main.check_messages",
|
client_request, uploaded_file_name, fake_uuid, mock_get_jobs
|
||||||
service_id=SERVICE_ONE_ID,
|
|
||||||
template_id="5d729fbd-239c-44ab-b498-75a985f3198f",
|
|
||||||
upload_id=fake_uuid,
|
|
||||||
original_file_name=uploaded_file_name,
|
|
||||||
_test_page_title=False,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert normalize_spaces(page.select_one(".banner-dangerous").text) == (
|
|
||||||
"These messages have already been sent today "
|
|
||||||
"If you need to resend them, rename the file and upload it again."
|
|
||||||
)
|
|
||||||
|
|
||||||
mock_get_jobs.assert_called_once_with(SERVICE_ONE_ID, limit_days=0)
|
def stmt_for_test_warns_if_file_sent_already_errors(
|
||||||
|
client_request, uploaded_file_name, fake_uuid, mock_get_jobs
|
||||||
|
):
|
||||||
|
page = client_request.get(
|
||||||
|
"main.check_messages",
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
template_id="5d729fbd-239c-44ab-b498-75a985f3198f",
|
||||||
|
upload_id=fake_uuid,
|
||||||
|
original_file_name=uploaded_file_name,
|
||||||
|
_test_page_title=False,
|
||||||
|
)
|
||||||
|
assert normalize_spaces(page.select_one(".banner-dangerous").text) == (
|
||||||
|
"These messages have already been sent today "
|
||||||
|
"If you need to resend them, rename the file and upload it again."
|
||||||
|
)
|
||||||
|
mock_get_jobs.assert_called_once_with(SERVICE_ONE_ID, limit_days=0)
|
||||||
|
|
||||||
|
|
||||||
def test_check_messages_column_error_doesnt_show_optional_columns(
|
def test_check_messages_column_error_doesnt_show_optional_columns(
|
||||||
|
|||||||
@@ -1117,25 +1117,31 @@ def test_should_show_checkboxes_for_selecting_templates_assertion_error(
|
|||||||
mock_get_no_api_keys,
|
mock_get_no_api_keys,
|
||||||
user,
|
user,
|
||||||
):
|
):
|
||||||
with pytest.raises( # noqa: PT012 # This will require more research into refactoring.
|
with pytest.raises(expected_exception=AssertionError):
|
||||||
expected_exception=AssertionError
|
_stmt_for_test_should_show_checkboxes_for_selecting_templates_assertion_error(
|
||||||
):
|
client_request, user
|
||||||
client_request.login(user)
|
|
||||||
|
|
||||||
page = client_request.get(
|
|
||||||
"main.choose_template",
|
|
||||||
service_id=SERVICE_ONE_ID,
|
|
||||||
)
|
)
|
||||||
checkboxes = page.select("input[name=templates_and_folders]")
|
|
||||||
|
|
||||||
assert len(checkboxes) == 4
|
|
||||||
|
|
||||||
assert checkboxes[0]["value"] == TEMPLATE_ONE_ID
|
def _stmt_for_test_should_show_checkboxes_for_selecting_templates_assertion_error(
|
||||||
assert checkboxes[0]["id"] == "templates-or-folder-{}".format(TEMPLATE_ONE_ID)
|
client_request, user
|
||||||
|
):
|
||||||
|
client_request.login(user)
|
||||||
|
|
||||||
for index in (1, 2, 3):
|
page = client_request.get(
|
||||||
assert checkboxes[index]["value"] != TEMPLATE_ONE_ID
|
"main.choose_template",
|
||||||
assert TEMPLATE_ONE_ID not in checkboxes[index]["id"]
|
service_id=SERVICE_ONE_ID,
|
||||||
|
)
|
||||||
|
checkboxes = page.select("input[name=templates_and_folders]")
|
||||||
|
|
||||||
|
assert len(checkboxes) == 4
|
||||||
|
|
||||||
|
assert checkboxes[0]["value"] == TEMPLATE_ONE_ID
|
||||||
|
assert checkboxes[0]["id"] == "templates-or-folder-{}".format(TEMPLATE_ONE_ID)
|
||||||
|
|
||||||
|
for index in (1, 2, 3):
|
||||||
|
assert checkboxes[index]["value"] != TEMPLATE_ONE_ID
|
||||||
|
assert TEMPLATE_ONE_ID not in checkboxes[index]["id"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ def test_should_show_live_search_if_service_has_lots_of_folders(
|
|||||||
assert count_of_templates == 4
|
assert count_of_templates == 4
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize( # noqa: PT014 # Requires more research why there are duplicate params here.
|
@pytest.mark.parametrize(
|
||||||
("service_permissions", "expected_values", "expected_labels"),
|
("service_permissions", "expected_values", "expected_labels"),
|
||||||
[
|
[
|
||||||
pytest.param(
|
pytest.param(
|
||||||
@@ -320,19 +320,20 @@ def test_should_show_live_search_if_service_has_lots_of_folders(
|
|||||||
"Copy an existing template",
|
"Copy an existing template",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
pytest.param(
|
# TODO This is a duplicate of above. Why?
|
||||||
["email", "sms"],
|
# pytest.param(
|
||||||
[
|
# ["email", "sms"],
|
||||||
# 'email',
|
# [
|
||||||
"sms",
|
# # 'email',
|
||||||
"copy-existing",
|
# "sms",
|
||||||
],
|
# "copy-existing",
|
||||||
[
|
# ],
|
||||||
# 'Email',
|
# [
|
||||||
"Start with a blank template",
|
# # 'Email',
|
||||||
"Copy an existing template",
|
# "Start with a blank template",
|
||||||
],
|
# "Copy an existing template",
|
||||||
),
|
# ],
|
||||||
|
# ),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_should_show_new_template_choices_if_service_has_folder_permission(
|
def test_should_show_new_template_choices_if_service_has_folder_permission(
|
||||||
@@ -753,9 +754,9 @@ def test_choose_a_template_to_copy(
|
|||||||
|
|
||||||
assert len(actual) == len(expected)
|
assert len(actual) == len(expected)
|
||||||
|
|
||||||
for actual, expected in zip(actual, expected): # noqa: B020
|
zipobject = zip(actual, expected)
|
||||||
|
for actual, expected in zipobject:
|
||||||
assert normalize_spaces(actual.text) == expected
|
assert normalize_spaces(actual.text) == expected
|
||||||
|
|
||||||
links = page.select("main nav a")
|
links = page.select("main nav a")
|
||||||
assert links[0]["href"] == url_for(
|
assert links[0]["href"] == url_for(
|
||||||
"main.choose_template_to_copy",
|
"main.choose_template_to_copy",
|
||||||
@@ -799,7 +800,8 @@ def test_choose_a_template_to_copy_when_user_has_one_service(
|
|||||||
|
|
||||||
assert len(actual) == len(expected)
|
assert len(actual) == len(expected)
|
||||||
|
|
||||||
for actual, expected in zip(actual, expected): # noqa: B020
|
zipobject = zip(actual, expected)
|
||||||
|
for actual, expected in zipobject:
|
||||||
assert normalize_spaces(actual.text) == expected
|
assert normalize_spaces(actual.text) == expected
|
||||||
|
|
||||||
assert page.select("main nav a")[0]["href"] == url_for(
|
assert page.select("main nav a")[0]["href"] == url_for(
|
||||||
@@ -875,7 +877,8 @@ def test_choose_a_template_to_copy_from_folder_within_service(
|
|||||||
|
|
||||||
assert len(actual) == len(expected)
|
assert len(actual) == len(expected)
|
||||||
|
|
||||||
for actual, expected in zip(actual, expected): # noqa: B020
|
zipobject = zip(actual, expected)
|
||||||
|
for actual, expected in zipobject:
|
||||||
assert normalize_spaces(actual.text) == expected
|
assert normalize_spaces(actual.text) == expected
|
||||||
|
|
||||||
links = page.select("main nav a")
|
links = page.select("main nav a")
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def test_should_show_overview_page(
|
|||||||
client_request,
|
client_request,
|
||||||
):
|
):
|
||||||
page = client_request.get("main.user_profile")
|
page = client_request.get("main.user_profile")
|
||||||
assert page.select_one("h1").text.strip() == "Your profile"
|
assert page.select_one("h1").text.strip() == "User profile"
|
||||||
assert "Use platform admin view" not in page
|
assert "Use platform admin view" not in page
|
||||||
assert "Security keys" not in page
|
assert "Security keys" not in page
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ def test_overview_page_shows_disable_for_platform_admin(
|
|||||||
):
|
):
|
||||||
client_request.login(platform_admin_user)
|
client_request.login(platform_admin_user)
|
||||||
page = client_request.get("main.user_profile")
|
page = client_request.get("main.user_profile")
|
||||||
assert page.select_one("h1").text.strip() == "Your profile"
|
assert page.select_one("h1").text.strip() == "User profile"
|
||||||
disable_platform_admin_row = page.select_one("#disable-platform-admin")
|
disable_platform_admin_row = page.select_one("#disable-platform-admin")
|
||||||
assert (
|
assert (
|
||||||
" ".join(disable_platform_admin_row.text.split())
|
" ".join(disable_platform_admin_row.text.split())
|
||||||
@@ -365,7 +365,7 @@ def test_non_gov_user_cannot_see_change_email_link(
|
|||||||
client_request.login(api_nongov_user_active)
|
client_request.login(api_nongov_user_active)
|
||||||
page = client_request.get("main.user_profile")
|
page = client_request.get("main.user_profile")
|
||||||
assert not page.find("a", {"href": url_for("main.user_profile_email")})
|
assert not page.find("a", {"href": url_for("main.user_profile_email")})
|
||||||
assert page.select_one("h1").text.strip() == "Your profile"
|
assert page.select_one("h1").text.strip() == "User profile"
|
||||||
|
|
||||||
|
|
||||||
def test_non_gov_user_cannot_access_change_email_page(
|
def test_non_gov_user_cannot_access_change_email_page(
|
||||||
|
|||||||
@@ -192,18 +192,11 @@ def test_returns_value_from_cache(
|
|||||||
assert mock_redis_set.call_args_list == expected_cache_set_calls
|
assert mock_redis_set.call_args_list == expected_cache_set_calls
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize( # noqa: PT014 # Duplicate add_user_to_service has different params for each
|
@pytest.mark.parametrize(
|
||||||
("client", "method", "extra_args", "extra_kwargs"),
|
("client", "method", "extra_args", "extra_kwargs"),
|
||||||
[
|
[
|
||||||
(
|
|
||||||
user_api_client,
|
|
||||||
"add_user_to_service",
|
|
||||||
[SERVICE_ONE_ID, sample_uuid(), [], []],
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
(user_api_client, "update_user_attribute", [user_id], {}),
|
(user_api_client, "update_user_attribute", [user_id], {}),
|
||||||
(user_api_client, "reset_failed_login_count", [user_id], {}),
|
(user_api_client, "reset_failed_login_count", [user_id], {}),
|
||||||
(user_api_client, "update_user_attribute", [user_id], {}),
|
|
||||||
(user_api_client, "update_password", [user_id, "hunter2"], {}),
|
(user_api_client, "update_password", [user_id, "hunter2"], {}),
|
||||||
(user_api_client, "verify_password", [user_id, "hunter2"], {}),
|
(user_api_client, "verify_password", [user_id, "hunter2"], {}),
|
||||||
(user_api_client, "check_verify_code", [user_id, "", ""], {}),
|
(user_api_client, "check_verify_code", [user_id, "", ""], {}),
|
||||||
|
|||||||
@@ -134,8 +134,7 @@ def test_does_not_delete_non_temp_email_file(client_request, mocker):
|
|||||||
"app.s3_client.s3_logo_client.delete_s3_object"
|
"app.s3_client.s3_logo_client.delete_s3_object"
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises(ValueError) as error: # noqa: PT011 # Requires more research.
|
with pytest.raises(ValueError, match="Not a temp file: logo.png"):
|
||||||
delete_email_temp_file(filename)
|
delete_email_temp_file(filename)
|
||||||
|
|
||||||
assert mocked_delete_s3_object.called is False
|
assert mocked_delete_s3_object.called is False
|
||||||
assert str(error.value) == "Not a temp file: {}".format(filename)
|
|
||||||
|
|||||||
@@ -354,7 +354,6 @@ def test_raises_on_invalid_navigation_item(client_request, navigation_instance):
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("endpoint", "selected_nav_item"),
|
("endpoint", "selected_nav_item"),
|
||||||
[
|
[
|
||||||
("main.choose_template", "Send messages"),
|
|
||||||
("main.manage_users", "Team members"),
|
("main.manage_users", "Team members"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -423,9 +422,9 @@ def test_navigation_urls(
|
|||||||
mock_get_api_keys,
|
mock_get_api_keys,
|
||||||
):
|
):
|
||||||
page = client_request.get("main.choose_template", service_id=SERVICE_ONE_ID)
|
page = client_request.get("main.choose_template", service_id=SERVICE_ONE_ID)
|
||||||
assert [a["href"] for a in page.select(".nav.margin-bottom-5 a")] == [
|
assert [a["href"] for a in page.select(".nav a")] == [
|
||||||
"/services/{}".format(SERVICE_ONE_ID),
|
|
||||||
"/services/{}/templates".format(SERVICE_ONE_ID),
|
"/services/{}/templates".format(SERVICE_ONE_ID),
|
||||||
|
"/services/{}".format(SERVICE_ONE_ID),
|
||||||
"/services/{}/users".format(SERVICE_ONE_ID),
|
"/services/{}/users".format(SERVICE_ONE_ID),
|
||||||
"/services/{}/usage".format(SERVICE_ONE_ID),
|
"/services/{}/usage".format(SERVICE_ONE_ID),
|
||||||
"/services/{}/service-settings".format(SERVICE_ONE_ID),
|
"/services/{}/service-settings".format(SERVICE_ONE_ID),
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ from werkzeug.exceptions import Forbidden
|
|||||||
from app.utils.user import user_has_permissions
|
from app.utils.user import user_has_permissions
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize( # noqa: PT007 # Ignoring wrong values type because of the list unpacking in the test.
|
@pytest.mark.parametrize(
|
||||||
"permissions",
|
"permissions",
|
||||||
(
|
[
|
||||||
[
|
[
|
||||||
# Route has one of the permissions which the user has
|
# Route has one of the permissions which the user has
|
||||||
"manage_service"
|
"manage_service"
|
||||||
@@ -25,7 +25,7 @@ from app.utils.user import user_has_permissions
|
|||||||
[
|
[
|
||||||
# Route has no specific permissions required
|
# Route has no specific permissions required
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
)
|
)
|
||||||
def test_permissions(
|
def test_permissions(
|
||||||
client_request,
|
client_request,
|
||||||
@@ -48,14 +48,14 @@ def test_permissions(
|
|||||||
index()
|
index()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize( # noqa: PT007 # Ignoring wrong values type because of the list unpacking in the test.
|
@pytest.mark.parametrize(
|
||||||
"permissions",
|
"permissions",
|
||||||
(
|
[
|
||||||
[
|
[
|
||||||
# Route has a permission which the user doesn’t have
|
# Route has a permission which the user doesn’t have
|
||||||
"send_messages"
|
"send_messages"
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
)
|
)
|
||||||
def test_permissions_forbidden(
|
def test_permissions_forbidden(
|
||||||
client_request,
|
client_request,
|
||||||
|
|||||||
+8
-1
@@ -2423,8 +2423,15 @@ def _os_environ():
|
|||||||
os.environ[k] = v
|
os.environ[k] = v
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture # noqa (C901 too complex)
|
@pytest.fixture() # noqa (C901 too complex)
|
||||||
def client_request(logged_in_client, mocker, service_one): # noqa (C901 too complex)
|
def client_request(logged_in_client, mocker, service_one): # noqa (C901 too complex)
|
||||||
|
def _get(mocker):
|
||||||
|
return {"count": 0}
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
"app.service_api_client.get_global_notification_count", side_effect=_get
|
||||||
|
)
|
||||||
|
|
||||||
class ClientRequest:
|
class ClientRequest:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
|||||||
Reference in New Issue
Block a user