mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-13 10:28:51 -04:00
Merge pull request #1238 from GSA/e2e-tests-docs
Add E2E documentation and clean E2E tests
This commit is contained in:
@@ -106,6 +106,104 @@ All of the E2E tests are found in the `tests/end_to_end` folder and are
|
||||
written as `pytest` scripts using
|
||||
[Playwright's Python Framework](https://playwright.dev/python/docs/writing-tests).
|
||||
|
||||
Inside the `tests/end_to_end` folder you'll see a `conftest.py` file,
|
||||
which is similar to the one found in the root `tests` folder but is
|
||||
specific to the E2E tests.
|
||||
|
||||
There a few fixtures defined in here, but the two most important at this
|
||||
time are these:
|
||||
|
||||
- `end_to_end_context`: A Playwright context object needed to interact
|
||||
with a browser instance.
|
||||
- `authenticated_page`: A Playwright page object that has gone through
|
||||
the sign in process the E2E user is authenticated.
|
||||
|
||||
In short, if you're starting a test from scratch and testing pages that
|
||||
do not require authentication, you'll start with the
|
||||
`end_to_end_context` fixture and work from there.
|
||||
|
||||
Any test that requires you to be authenticated, you'll start with the
|
||||
`authenticated_page` object as that'll have taken care of getting
|
||||
everything set for you and logged into the site with the E2E test user.
|
||||
|
||||
|
||||
### Creating a new test file
|
||||
|
||||
If you want to create a new test file to help organize tests (a great
|
||||
idea!), it will be handy to import the Playwright `expect` and set the
|
||||
base URL/URI for yourself, like this:
|
||||
|
||||
```python
|
||||
from playwright.sync_api import expect
|
||||
|
||||
E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
|
||||
```
|
||||
|
||||
By importing Playwright's `expect` object for tests and setting
|
||||
something like `E2E_TEST_URI` for yourself, it will make writing tests
|
||||
much easier.
|
||||
|
||||
|
||||
### Using the fixtures
|
||||
|
||||
To use the `authenticated_page` or `end_to_end_context` fixtures, you
|
||||
start by defining a test function and then passing in the fixture you
|
||||
need as a positional argument. This works the same as the other
|
||||
functions defined to create a test for pytest.
|
||||
|
||||
For example, the test for the landing page starts with this:
|
||||
|
||||
```python
|
||||
def test_landing_page(end_to_end_context):
|
||||
# Open a new page and go to the site.
|
||||
page = end_to_end_context.browser.new_page()
|
||||
page.goto(f"{E2E_TEST_URI}/")
|
||||
|
||||
# Check to make sure that we've arrived at the next page.
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
...
|
||||
```
|
||||
|
||||
Note the passing in of the `end_to_end_context` fixture - there is no
|
||||
need to import this or anything, just pass it into the function. pytest
|
||||
takes care of everything else for you.
|
||||
|
||||
The second line that defines a `page` variable is a convenience, since
|
||||
you'll be referencing the page object a lot. This is recommended to
|
||||
help keep tests readable while keeping fixture names descriptive.
|
||||
|
||||
If you need to test an authenticate page, such as the accounts page,
|
||||
use the `authenticated_page` fixture instead, like so:
|
||||
|
||||
```python
|
||||
def test_add_new_service_workflow(authenticated_page):
|
||||
page = authenticated_page
|
||||
...
|
||||
```
|
||||
|
||||
Again, it's helpful to assign the fixture to a `page` variable for easy
|
||||
reference throughout the test.
|
||||
|
||||
Lastly, if you need want access to the Playwright context object that is
|
||||
used behind the page fixtures, you can reference it directly as well
|
||||
using the `end_to_end_context` fixture:
|
||||
|
||||
```python
|
||||
def test_add_new_service_workflow(authenticated_page, end_to_end_context):
|
||||
page = authenticated_page
|
||||
|
||||
# Prepare for adding a new service later in the test.
|
||||
current_date_time = datetime.datetime.now()
|
||||
new_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,
|
||||
)
|
||||
...
|
||||
```
|
||||
|
||||
In this example, I've used the context to get to the browser object
|
||||
itself to get the name of the browser for test data.
|
||||
|
||||
|
||||
## Maintaining E2E Tests with GitHub
|
||||
|
||||
|
||||
@@ -862,9 +862,9 @@ def test_should_show_page_if_prefilled_user_is_already_invited(
|
||||
mock_get_invites_for_service,
|
||||
platform_admin_user,
|
||||
):
|
||||
active_user_with_permission_to_other_service[
|
||||
"email_address"
|
||||
] = "user_1@testnotify.gsa.gov"
|
||||
active_user_with_permission_to_other_service["email_address"] = (
|
||||
"user_1@testnotify.gsa.gov"
|
||||
)
|
||||
client_request.login(platform_admin_user)
|
||||
mocker.patch(
|
||||
"app.models.user.user_api_client.get_user",
|
||||
|
||||
@@ -31,9 +31,11 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None):
|
||||
"name": name,
|
||||
"id": folder_id or str(uuid.uuid4()),
|
||||
"parent_id": parent,
|
||||
"users_with_permission": users_with_permission
|
||||
if users_with_permission is not None
|
||||
else [sample_uuid()],
|
||||
"users_with_permission": (
|
||||
users_with_permission
|
||||
if users_with_permission is not None
|
||||
else [sample_uuid()]
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -904,9 +904,11 @@ def create_service_templates(service_id, number_of_templates=4):
|
||||
"{}_template_{}".format(template_type, template_number),
|
||||
template_type,
|
||||
"{} template {} content".format(template_type, template_number),
|
||||
subject="{} template {} subject".format(template_type, template_number)
|
||||
if template_type == "email"
|
||||
else None,
|
||||
subject=(
|
||||
"{} template {} subject".format(template_type, template_number)
|
||||
if template_type == "email"
|
||||
else None
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1101,9 +1103,9 @@ def active_user_with_permission_to_other_service(
|
||||
active_user_with_permission_to_two_services["permissions"].pop(SERVICE_ONE_ID)
|
||||
active_user_with_permission_to_two_services["services"].pop(0)
|
||||
active_user_with_permission_to_two_services["name"] = "Service Two User"
|
||||
active_user_with_permission_to_two_services[
|
||||
"email_address"
|
||||
] = "service-two-user@test.gsa.gov"
|
||||
active_user_with_permission_to_two_services["email_address"] = (
|
||||
"service-two-user@test.gsa.gov"
|
||||
)
|
||||
return active_user_with_permission_to_two_services
|
||||
|
||||
|
||||
|
||||
@@ -68,12 +68,6 @@ def login_for_end_to_end_testing(browser):
|
||||
context.storage_state(path=auth_state_path)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def end_to_end_context(browser):
|
||||
context = browser.new_context()
|
||||
return context
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def end_to_end_authenticated_context(browser):
|
||||
# Create and load a previously authenticated context for Playwright E2E
|
||||
@@ -89,17 +83,25 @@ def end_to_end_authenticated_context(browser):
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def authenticated_page(end_to_end_context):
|
||||
# Open a new page and go to the staging site.
|
||||
page = end_to_end_context.new_page()
|
||||
def end_to_end_context(browser):
|
||||
context = browser.new_context()
|
||||
return context
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def authenticated_page(end_to_end_context):
|
||||
# Open a new page and go to the site.
|
||||
page = end_to_end_context.new_page()
|
||||
page.goto(f"{E2E_TEST_URI}/")
|
||||
|
||||
sign_in_button = page.get_by_role("link", name="Sign in")
|
||||
# Wait for the next page to fully load.
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
|
||||
# Sign in to the site - E2E test accounts are set to flow through.
|
||||
sign_in_button = page.get_by_role("link", name="Sign in")
|
||||
sign_in_button.click()
|
||||
|
||||
# Wait for the next page to fully load.
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
|
||||
return page
|
||||
|
||||
@@ -9,10 +9,6 @@ E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
|
||||
|
||||
def test_add_new_service_workflow(authenticated_page, end_to_end_context):
|
||||
page = authenticated_page
|
||||
page.goto(f"{E2E_TEST_URI}/")
|
||||
|
||||
# Wait for the next page to fully load.
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
|
||||
# Prepare for adding a new service later in the test.
|
||||
current_date_time = datetime.datetime.now()
|
||||
|
||||
@@ -7,7 +7,7 @@ E2E_TEST_URI = os.getenv("NOTIFY_E2E_TEST_URI")
|
||||
|
||||
|
||||
def test_landing_page(end_to_end_context):
|
||||
# Open a new page and go to the staging site.
|
||||
# Open a new page and go to the site.
|
||||
page = end_to_end_context.browser.new_page()
|
||||
page.goto(f"{E2E_TEST_URI}/")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user