mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-06-29 20:00:24 -04:00
162 lines
4.8 KiB
Python
162 lines
4.8 KiB
Python
import datetime
|
|
import os
|
|
|
|
import pytest
|
|
from axe_core_python.sync_playwright import Axe
|
|
from playwright.sync_api import Page
|
|
|
|
E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
|
|
|
|
|
|
@pytest.fixture
|
|
def end_to_end_context(browser):
|
|
context = browser.new_context()
|
|
return context
|
|
|
|
|
|
@pytest.fixture
|
|
def authenticated_page(end_to_end_context):
|
|
page = end_to_end_context.new_page()
|
|
page.goto(f"{E2E_TEST_URI}/sign-in")
|
|
page.wait_for_load_state("domcontentloaded")
|
|
return page
|
|
|
|
|
|
def check_axe_report(page):
|
|
axe = Axe()
|
|
results = axe.run(page)
|
|
|
|
filtered_violations = []
|
|
for violation in results["violations"]:
|
|
keep = True
|
|
for node in violation["nodes"]:
|
|
for target in node.get("target", []):
|
|
# Skip known Flask debug elements like werkzeug or debugger footer
|
|
if (
|
|
"werkzeug" in target
|
|
or ".debugger" in target
|
|
or ".footer" in target
|
|
or "DON'T PANIC" in node.get("html", "")
|
|
):
|
|
keep = False
|
|
if keep:
|
|
filtered_violations.append(violation)
|
|
|
|
for violation in filtered_violations:
|
|
assert violation["impact"] in [
|
|
"minor",
|
|
"moderate",
|
|
], f"Accessibility violation: {violation}"
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _mock_common_api_calls(mocker):
|
|
# Patch the health check so it doesn't hit external endpoints
|
|
mocker.patch("app.utils.api_health.is_api_down", return_value=False)
|
|
|
|
# Add more global mocks as needed, like:
|
|
mocker.patch(
|
|
"app.service_api_client.get_service",
|
|
return_value={"id": "1234", "name": "Test Service"},
|
|
)
|
|
|
|
# Optional: silence New Relic or other external integrations
|
|
mocker.patch("newrelic.agent.initialize", return_value=None)
|
|
|
|
|
|
@pytest.fixture
|
|
def e2e_test_service(authenticated_page: Page, end_to_end_context):
|
|
"""
|
|
Creates a test service for E2E tests with guaranteed cleanup.
|
|
|
|
This fixture ensures services are deleted even if tests fail, preventing
|
|
database pollution from abandoned E2E test services.
|
|
"""
|
|
page = authenticated_page
|
|
current_date_time = datetime.datetime.now()
|
|
service_name = "E2E Federal Test Service {now} - {browser_type}".format(
|
|
now=current_date_time.strftime("%m/%d/%Y %H:%M:%S"),
|
|
browser_type=end_to_end_context.browser.browser_type.name,
|
|
)
|
|
|
|
service_info = {
|
|
"name": service_name,
|
|
"page": page,
|
|
}
|
|
|
|
yield service_info
|
|
|
|
# runs even if test fails
|
|
try:
|
|
_cleanup_test_service(page, service_name)
|
|
except Exception as e:
|
|
print(f"Warning: Failed to cleanup service '{service_name}': {e}") # noqa: T201
|
|
|
|
|
|
@pytest.fixture
|
|
def e2e_created_service(e2e_test_service): # noqa: PT022
|
|
"""
|
|
Creates a test service AND completes the service creation workflow.
|
|
|
|
This fixture not only generates a unique service name but also creates
|
|
the service through the UI, providing a ready-to-use service for tests.
|
|
"""
|
|
service_info = e2e_test_service
|
|
page = service_info["page"]
|
|
service_name = service_info["name"]
|
|
|
|
page.goto(f"{E2E_TEST_URI}/accounts")
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
add_service_button = page.get_by_role("button", name="Add service")
|
|
add_service_button.click()
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
service_name_input = page.locator('xpath=//input[@name="name"]')
|
|
service_name_input.fill(service_name)
|
|
|
|
add_button = page.get_by_role("button", name="Add service")
|
|
add_button.click()
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
service_info["url"] = page.url
|
|
|
|
yield service_info
|
|
|
|
|
|
def _cleanup_test_service(page: Page, service_name: str):
|
|
"""
|
|
Delete a test service by navigating to its settings and clicking delete.
|
|
|
|
Args:
|
|
page: Playwright page object
|
|
service_name: Name of the service to delete
|
|
"""
|
|
try:
|
|
page.goto(f"{E2E_TEST_URI}/accounts")
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
service_link = page.get_by_role("link", name=service_name)
|
|
|
|
if service_link.count() > 0:
|
|
service_link.click()
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
page.click("text='Settings'")
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
page.click("text='Delete this service'")
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
page.click("text='Yes, delete'")
|
|
page.wait_for_load_state("domcontentloaded")
|
|
|
|
print(f"Successfully cleaned up test service: {service_name}") # noqa: T201
|
|
else:
|
|
print( # noqa: T201
|
|
f"Service '{service_name}' not found, may have been deleted already"
|
|
)
|
|
|
|
except Exception as e:
|
|
raise Exception(f"Failed to cleanup service '{service_name}': {str(e)}")
|