merge from main

This commit is contained in:
Kenneth Kehl
2023-11-02 14:13:43 -07:00
38 changed files with 441 additions and 298 deletions
+10 -2
View File
@@ -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
+17
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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 (
+76
View File
@@ -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",
+2 -9
View File
@@ -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()
+11 -1
View File
@@ -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')
}, },
{ {
+2 -8
View File
@@ -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, theres 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>
+8 -6
View File
@@ -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 %}
+1 -1
View File
@@ -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 -3
View File
@@ -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
) %} ) %}
+2 -2
View File
@@ -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
View File
@@ -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 |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| |-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
+23 -23
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+2 -2
View File
@@ -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):
+8 -2
View File
@@ -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, theres 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, theres a problem with the service Notify.gov" == "Sorry, theres 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, theres 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, theres a problem with the service Notify.gov" == "Sorry, theres a problem with the service Notify.gov"
+1
View File
@@ -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,
+8
View File
@@ -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,
+2 -1
View File
@@ -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)
+2 -1
View File
@@ -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 -65
View File
@@ -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)
+4 -2
View File
@@ -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",
+21 -15
View File
@@ -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(
+21 -15
View File
@@ -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(
+21 -18
View File
@@ -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")
+3 -3
View File
@@ -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(
+1 -8
View File
@@ -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, "", ""], {}),
+1 -2
View File
@@ -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)
+2 -3
View File
@@ -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),
+6 -6
View File
@@ -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 doesnt have # Route has a permission which the user doesnt have
"send_messages" "send_messages"
], ],
), ],
) )
def test_permissions_forbidden( def test_permissions_forbidden(
client_request, client_request,
+8 -1
View File
@@ -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